<commit_before>use clap::{arg, error::ErrorKind, Arg, ArgAction, ArgGroup, Command, Id};

use super::utils;

#[test]
fn required_group_missing_arg() {
    let result = Command::new("group")
        .arg(arg!(-f --flag "some flag"))
        .arg(arg!( -c --color "some other flag"))
        .group(ArgGroup::new("req").args(["flag", "color"]).required(true))
        .try_get_matches_from(vec![""]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
}

#[cfg(debug_assertions)]
#[test]
#[should_panic = "Command group: Argument group 'req' contains non-existent argument"]
fn non_existing_arg() {
    let _ = Command::new("group")
        .arg(arg!(-f --flag "some flag"))
        .arg(arg!(-c --color "some other flag"))
        .group(ArgGroup::new("req").args(["flg", "color"]).required(true))
        .try_get_matches_from(vec![""]);
}

#[cfg(debug_assertions)]
#[test]
#[should_panic = "Command group: Argument group name must be unique\n\n\t'req' is already in use"]
fn unique_group_name() {
    let _ = Command::new("group")
        .arg(arg!(-f --flag "some flag"))
        .arg(arg!(-c --color "some other flag"))
        .group(ArgGroup::new("req").args(["flag"]).required(true))
        .group(ArgGroup::new("req").args(["color"]).required(true))
        .try_get_matches_from(vec![""]);
}

#[cfg(debug_assertions)]
#[test]
#[should_panic = "Command group: Argument group name 'a' must not conflict with argument name"]
fn groups_new_of_arg_name() {
    let _ = Command::new("group")
        .arg(Arg::new("a").long("a").group("a"))
        .try_get_matches_from(vec!["", "--a"]);
}

#[cfg(debug_assertions)]
#[test]
#[should_panic = "Command group: Argument group name 'a' must not conflict with argument name"]
fn arg_group_new_of_arg_name() {
    let _ = Command::new("group")
        .arg(Arg::new("a").long("a").group("a"))
        .group(ArgGroup::new("a"))
        .try_get_matches_from(vec!["", "--a"]);
}

#[test]
fn group_single_value() {
    let res = Command::new("group")
        .arg(arg!(-c --color [color] "some option"))
        .arg(arg!(-n --hostname <name> "another option"))
        .group(ArgGroup::new("grp").args(["hostname", "color"]))
        .try_get_matches_from(vec!["", "-c", "blue"]);
    assert!(res.is_ok(), "{}", res.unwrap_err());

    let m = res.unwrap();
    assert!(m.contains_id("grp"));
    assert_eq!(m.get_one::<Id>("grp").map(|v| v.as_str()).unwrap(), "color");
}

#[test]
fn group_empty() {
    let res = Command::new("group")
        .arg(arg!(-c --color [color] "some option"))
        .arg(arg!(-n --hostname <name> "another option"))
        .group(ArgGroup::new("grp").args(["hostname", "color"]))
        .try_get_matches_from(vec![""]);
    assert!(res.is_ok(), "{}", res.unwrap_err());

    let m = res.unwrap();
    assert!(!m.contains_id("grp"));
    assert!(m.get_one::<String>("grp").map(|v| v.as_str()).is_none());
}

#[test]
fn group_required_flags_empty() {
    let result = Command::new("group")
        .arg(arg!(-c --color "some option"))
        .arg(arg!(-n --hostname <name> "another option"))
        .group(
            ArgGroup::new("grp")
                .required(true)
                .args(["hostname", "color"]),
        )
        .try_get_matches_from(vec![""]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
}

#[test]
fn group_multi_value_single_arg() {
    let res = Command::new("group")
        .arg(arg!(-c --color <color> "some option").num_args(1..))
        .arg(arg!(-n --hostname <name> "another option"))
        .group(ArgGroup::new("grp").args(["hostname", "color"]))
        .try_get_matches_from(vec!["", "-c", "blue", "red", "green"]);
    assert!(res.is_ok(), "{:?}", res.unwrap_err().kind());

    let m = res.unwrap();
    assert!(m.contains_id("grp"));
    assert_eq!(m.get_one::<Id>("grp").map(|v| v.as_str()).unwrap(), "color");
}

#[test]
fn empty_group() {
    let r = Command::new("empty_group")
        .arg(arg!(-f --flag "some flag"))
        .group(ArgGroup::new("vers").required(true))
        .try_get_matches_from(vec!["empty_prog"]);
    assert!(r.is_err());
    let err = r.err().unwrap();
    assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
}

#[test]
#[cfg(feature = "error-context")]
fn req_group_usage_string() {
    static REQ_GROUP_USAGE: &str = "error: The following required arguments were not provided:
  <base|--delete>

Usage: clap-test <base|--delete>

For more information try '--help'
";

    let cmd = Command::new("req_group")
        .arg(arg!([base] "Base commit"))
        .arg(arg!(
            -d --delete "Remove the base commit information"
        ))
        .group(
            ArgGroup::new("base_or_delete")
                .args(["base", "delete"])
                .required(true),
        );

    utils::assert_output(cmd, "clap-test", REQ_GROUP_USAGE, true);
}

#[test]
#[cfg(feature = "error-context")]
fn req_group_with_conflict_usage_string() {
    static REQ_GROUP_CONFLICT_USAGE: &str = "\
error: The argument '--delete' cannot be used with '[base]'

Usage: clap-test <base|--delete>

For more information try '--help'
";

    let cmd = Command::new("req_group")
        .arg(arg!([base] "Base commit").conflicts_with("delete"))
        .arg(arg!(
            -d --delete "Remove the base commit information"
        ))
        .group(
            ArgGroup::new("base_or_delete")
                .args(["base", "delete"])
                .required(true),
        );

    utils::assert_output(
        cmd,
        "clap-test --delete base",
        REQ_GROUP_CONFLICT_USAGE,
        true,
    );
}

#[test]
#[cfg(feature = "error-context")]
fn req_group_with_conflict_usage_string_only_options() {
    static REQ_GROUP_CONFLICT_ONLY_OPTIONS: &str = "\
error: The argument '--delete' cannot be used with '--all'

Usage: clap-test <--all|--delete>

For more information try '--help'
";

    let cmd = Command::new("req_group")
        .arg(arg!(-a --all "All").conflicts_with("delete"))
        .arg(arg!(
            -d --delete "Remove the base commit information"
        ))
        .group(
            ArgGroup::new("all_or_delete")
                .args(["all", "delete"])
                .required(true),
        );
    utils::assert_output(
        cmd,
        "clap-test --delete --all",
        REQ_GROUP_CONFLICT_ONLY_OPTIONS,
        true,
    );
}

#[test]
fn required_group_multiple_args() {
    let result = Command::new("group")
        .arg(arg!(-f --flag "some flag").action(ArgAction::SetTrue))
        .arg(arg!(-c --color "some other flag").action(ArgAction::SetTrue))
        .group(
            ArgGroup::new("req")
                .args(["flag", "color"])
                .required(true)
                .multiple(true),
        )
        .try_get_matches_from(vec!["group", "-f", "-c"]);
    assert!(result.is_ok(), "{}", result.unwrap_err());
    let m = result.unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
    assert_eq!(
        &*m.get_many::<Id>("req")
            .unwrap()
            .map(|v| v.as_str())
            .collect::<Vec<_>>(),
        &["flag", "color"]
    );
}

#[test]
fn group_multiple_args_error() {
    let result = Command::new("group")
        .arg(arg!(-f --flag "some flag"))
        .arg(arg!(-c --color "some other flag"))
        .group(ArgGroup::new("req").args(["flag", "color"]))
        .try_get_matches_from(vec!["group", "-f", "-c"]);
    assert!(result.is_err());
    let err = result.unwrap_err();
    assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
}

#[test]
fn group_overrides_required() {
    let command = Command::new("group")
        .arg(arg!(--foo <FOO>).required(true))
        .arg(arg!(--bar <BAR>).required(true))
        .group(ArgGroup::new("group").args(["foo", "bar"]).required(true));
    let result = command.try_get_matches_from(vec!["group", "--foo", "value"]);
    assert!(result.is_ok(), "{}", result.unwrap_err());
    let m = result.unwrap();
    assert!(m.contains_id("foo"));
    assert!(!m.contains_id("bar"));
}

#[test]
fn group_usage_use_val_name() {
    static GROUP_USAGE_USE_VAL_NAME: &str = "\
Usage: prog

Arguments:
  [A]

Options:
  -h, --help  Print help information
";
    let cmd = Command::new("prog")
        .arg(Arg::new("a").value_name("A"))
        .group(ArgGroup::new("group").arg("a").required(true));
    utils::assert_output(cmd, "prog --help", GROUP_USAGE_USE_VAL_NAME, false);
}

#[test]
fn group_acts_like_arg() {
    let result = Command::new("prog")
        .arg(
            Arg::new("debug")
                .long("debug")
                .group("mode")
                .action(ArgAction::SetTrue),
        )
        .arg(
            Arg::new("verbose")
                .long("verbose")
                .group("mode")
                .action(ArgAction::SetTrue),
        )
        .try_get_matches_from(vec!["prog", "--debug"]);

    assert!(result.is_ok(), "{}", result.unwrap_err());
    let m = result.unwrap();
    assert!(m.contains_id("mode"));
}

/* This is used to be fixed in a hack, we need to find a better way to fix it.
#[test]
fn issue_1794() {
    let cmd = clap::Command::new("hello")
        .bin_name("deno")
        .arg(Arg::new("option1").long("option1").action(ArgAction::SetTrue))
        .arg(Arg::new("pos1").action(ArgAction::Set))
        .arg(Arg::new("pos2").action(ArgAction::Set))
        .group(
            ArgGroup::new("arg1")
                .args(["pos1", "option1"])
                .required(true),
        );

    let m = cmd.clone().try_get_matches_from(&["cmd", "pos1", "pos2"]).unwrap();
    assert_eq!(m.get_one::<String>("pos1").map(|v| v.as_str()), Some("pos1"));
    assert_eq!(m.get_one::<String>("pos2").map(|v| v.as_str()), Some("pos2"));
    assert!(!*m.get_one::<bool>("option1").expect("defaulted by clap"));

    let m = cmd
        .clone()
        .try_get_matches_from(&["cmd", "--option1", "positional"]).unwrap();
    assert_eq!(m.get_one::<String>("pos1").map(|v| v.as_str()), None);
    assert_eq!(m.get_one::<String>("pos2").map(|v| v.as_str()), Some("positional"));
    assert!(*m.get_one::<bool>("option1").expect("defaulted by clap"));
}
*/
<commit_msg>test: Expand group test<commit_after>use clap::{arg, error::ErrorKind, Arg, ArgAction, ArgGroup, Command, Id};

use super::utils;

#[test]
fn required_group_missing_arg() {
    let result = Command::new("group")
        .arg(arg!(-f --flag "some flag"))
        .arg(arg!( -c --color "some other flag"))
        .group(ArgGroup::new("req").args(["flag", "color"]).required(true))
        .try_get_matches_from(vec![""]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
}

#[cfg(debug_assertions)]
#[test]
#[should_panic = "Command group: Argument group 'req' contains non-existent argument"]
fn non_existing_arg() {
    let _ = Command::new("group")
        .arg(arg!(-f --flag "some flag"))
        .arg(arg!(-c --color "some other flag"))
        .group(ArgGroup::new("req").args(["flg", "color"]).required(true))
        .try_get_matches_from(vec![""]);
}

#[cfg(debug_assertions)]
#[test]
#[should_panic = "Command group: Argument group name must be unique\n\n\t'req' is already in use"]
fn unique_group_name() {
    let _ = Command::new("group")
        .arg(arg!(-f --flag "some flag"))
        .arg(arg!(-c --color "some other flag"))
        .group(ArgGroup::new("req").args(["flag"]).required(true))
        .group(ArgGroup::new("req").args(["color"]).required(true))
        .try_get_matches_from(vec![""]);
}

#[cfg(debug_assertions)]
#[test]
#[should_panic = "Command group: Argument group name 'a' must not conflict with argument name"]
fn groups_new_of_arg_name() {
    let _ = Command::new("group")
        .arg(Arg::new("a").long("a").group("a"))
        .try_get_matches_from(vec!["", "--a"]);
}

#[cfg(debug_assertions)]
#[test]
#[should_panic = "Command group: Argument group name 'a' must not conflict with argument name"]
fn arg_group_new_of_arg_name() {
    let _ = Command::new("group")
        .arg(Arg::new("a").long("a").group("a"))
        .group(ArgGroup::new("a"))
        .try_get_matches_from(vec!["", "--a"]);
}

#[test]
fn group_single_value() {
    let res = Command::new("group")
        .arg(arg!(-c --color [color] "some option"))
        .arg(arg!(-n --hostname <name> "another option"))
        .group(ArgGroup::new("grp").args(["hostname", "color"]))
        .try_get_matches_from(vec!["", "-c", "blue"]);
    assert!(res.is_ok(), "{}", res.unwrap_err());

    let m = res.unwrap();
    assert!(m.contains_id("grp"));
    assert_eq!(m.get_one::<Id>("grp").map(|v| v.as_str()).unwrap(), "color");
}

#[test]
fn group_empty() {
    let res = Command::new("group")
        .arg(arg!(-c --color [color] "some option"))
        .arg(arg!(-n --hostname <name> "another option"))
        .group(ArgGroup::new("grp").args(["hostname", "color"]))
        .try_get_matches_from(vec![""]);
    assert!(res.is_ok(), "{}", res.unwrap_err());

    let m = res.unwrap();
    assert!(!m.contains_id("grp"));
    assert!(m.get_one::<String>("grp").map(|v| v.as_str()).is_none());
}

#[test]
fn group_required_flags_empty() {
    let result = Command::new("group")
        .arg(arg!(-c --color "some option"))
        .arg(arg!(-n --hostname <name> "another option"))
        .group(
            ArgGroup::new("grp")
                .required(true)
                .args(["hostname", "color"]),
        )
        .try_get_matches_from(vec![""]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
}

#[test]
fn group_multi_value_single_arg() {
    let res = Command::new("group")
        .arg(arg!(-c --color <color> "some option").num_args(1..))
        .arg(arg!(-n --hostname <name> "another option"))
        .group(ArgGroup::new("grp").args(["hostname", "color"]))
        .try_get_matches_from(vec!["", "-c", "blue", "red", "green"]);
    assert!(res.is_ok(), "{:?}", res.unwrap_err().kind());

    let m = res.unwrap();
    assert!(m.contains_id("grp"));
    assert_eq!(m.get_one::<Id>("grp").map(|v| v.as_str()).unwrap(), "color");
}

#[test]
fn empty_group() {
    let r = Command::new("empty_group")
        .arg(arg!(-f --flag "some flag"))
        .group(ArgGroup::new("vers").required(true))
        .try_get_matches_from(vec!["empty_prog"]);
    assert!(r.is_err());
    let err = r.err().unwrap();
    assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
}

#[test]
#[cfg(feature = "error-context")]
fn req_group_usage_string() {
    static REQ_GROUP_USAGE: &str = "error: The following required arguments were not provided:
  <base|--delete>

Usage: clap-test <base|--delete>

For more information try '--help'
";

    let cmd = Command::new("req_group")
        .arg(arg!([base] "Base commit"))
        .arg(arg!(
            -d --delete "Remove the base commit information"
        ))
        .group(
            ArgGroup::new("base_or_delete")
                .args(["base", "delete"])
                .required(true),
        );

    utils::assert_output(cmd, "clap-test", REQ_GROUP_USAGE, true);
}

#[test]
#[cfg(feature = "error-context")]
fn req_group_with_conflict_usage_string() {
    static REQ_GROUP_CONFLICT_USAGE: &str = "\
error: The argument '--delete' cannot be used with '[base]'

Usage: clap-test <base|--delete>

For more information try '--help'
";

    let cmd = Command::new("req_group")
        .arg(arg!([base] "Base commit").conflicts_with("delete"))
        .arg(arg!(
            -d --delete "Remove the base commit information"
        ))
        .group(
            ArgGroup::new("base_or_delete")
                .args(["base", "delete"])
                .required(true),
        );

    utils::assert_output(
        cmd,
        "clap-test --delete base",
        REQ_GROUP_CONFLICT_USAGE,
        true,
    );
}

#[test]
#[cfg(feature = "error-context")]
fn req_group_with_conflict_usage_string_only_options() {
    static REQ_GROUP_CONFLICT_ONLY_OPTIONS: &str = "\
error: The argument '--delete' cannot be used with '--all'

Usage: clap-test <--all|--delete>

For more information try '--help'
";

    let cmd = Command::new("req_group")
        .arg(arg!(-a --all "All").conflicts_with("delete"))
        .arg(arg!(
            -d --delete "Remove the base commit information"
        ))
        .group(
            ArgGroup::new("all_or_delete")
                .args(["all", "delete"])
                .required(true),
        );
    utils::assert_output(
        cmd,
        "clap-test --delete --all",
        REQ_GROUP_CONFLICT_ONLY_OPTIONS,
        true,
    );
}

#[test]
fn required_group_multiple_args() {
    let result = Command::new("group")
        .arg(arg!(-f --flag "some flag").action(ArgAction::SetTrue))
        .arg(arg!(-c --color "some other flag").action(ArgAction::SetTrue))
        .group(
            ArgGroup::new("req")
                .args(["flag", "color"])
                .required(true)
                .multiple(true),
        )
        .try_get_matches_from(vec!["group", "-f", "-c"]);
    assert!(result.is_ok(), "{}", result.unwrap_err());
    let m = result.unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
    assert_eq!(
        &*m.get_many::<Id>("req")
            .unwrap()
            .map(|v| v.as_str())
            .collect::<Vec<_>>(),
        &["flag", "color"]
    );
}

#[test]
fn group_multiple_args_error() {
    let result = Command::new("group")
        .arg(arg!(-f --flag "some flag"))
        .arg(arg!(-c --color "some other flag"))
        .group(ArgGroup::new("req").args(["flag", "color"]))
        .try_get_matches_from(vec!["group", "-f", "-c"]);
    assert!(result.is_err());
    let err = result.unwrap_err();
    assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
}

#[test]
fn group_overrides_required() {
    let command = Command::new("group")
        .arg(arg!(--foo <FOO>).required(true))
        .arg(arg!(--bar <BAR>).required(true))
        .group(ArgGroup::new("group").args(["foo", "bar"]).required(true));
    let result = command.try_get_matches_from(vec!["group", "--foo", "value"]);
    assert!(result.is_ok(), "{}", result.unwrap_err());
    let m = result.unwrap();
    assert!(m.contains_id("foo"));
    assert!(!m.contains_id("bar"));
}

#[test]
fn group_usage_use_val_name() {
    static GROUP_USAGE_USE_VAL_NAME: &str = "\
Usage: prog

Arguments:
  [A]

Options:
  -h, --help  Print help information
";
    let cmd = Command::new("prog")
        .arg(Arg::new("a").value_name("A"))
        .group(ArgGroup::new("group").arg("a").required(true));
    utils::assert_output(cmd, "prog --help", GROUP_USAGE_USE_VAL_NAME, false);
}

#[test]
fn group_acts_like_arg() {
    let result = Command::new("prog")
        .arg(
            Arg::new("debug")
                .long("debug")
                .group("mode")
                .action(ArgAction::SetTrue),
        )
        .arg(
            Arg::new("verbose")
                .long("verbose")
                .group("mode")
                .action(ArgAction::SetTrue),
        )
        .try_get_matches_from(vec!["prog", "--debug"]);

    assert!(result.is_ok(), "{}", result.unwrap_err());
    let m = result.unwrap();
    assert!(m.contains_id("mode"));
    assert_eq!(m.get_one::<clap::Id>("mode").unwrap(), "debug");
}

/* This is used to be fixed in a hack, we need to find a better way to fix it.
#[test]
fn issue_1794() {
    let cmd = clap::Command::new("hello")
        .bin_name("deno")
        .arg(Arg::new("option1").long("option1").action(ArgAction::SetTrue))
        .arg(Arg::new("pos1").action(ArgAction::Set))
        .arg(Arg::new("pos2").action(ArgAction::Set))
        .group(
            ArgGroup::new("arg1")
                .args(["pos1", "option1"])
                .required(true),
        );

    let m = cmd.clone().try_get_matches_from(&["cmd", "pos1", "pos2"]).unwrap();
    assert_eq!(m.get_one::<String>("pos1").map(|v| v.as_str()), Some("pos1"));
    assert_eq!(m.get_one::<String>("pos2").map(|v| v.as_str()), Some("pos2"));
    assert!(!*m.get_one::<bool>("option1").expect("defaulted by clap"));

    let m = cmd
        .clone()
        .try_get_matches_from(&["cmd", "--option1", "positional"]).unwrap();
    assert_eq!(m.get_one::<String>("pos1").map(|v| v.as_str()), None);
    assert_eq!(m.get_one::<String>("pos2").map(|v| v.as_str()), Some("positional"));
    assert!(*m.get_one::<bool>("option1").expect("defaulted by clap"));
}
*/
<|endoftext|>


<commit_before>/* Copyright 2016 Torbjørn Birch Moltu
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */

//! Test that methods gives the correct error.
//! Some also test a bit more because it's easy.

use std::char;
extern crate encode_unicode;
use encode_unicode::*;
use encode_unicode::error::*;

#[test]
fn from_u32() {
    use encode_unicode::error::InvalidCodepoint::*;
    for c in 0xd800..0xe000 {
        assert_eq!(char::from_u32_detailed(c),  Err(Utf16Reserved));
    }
    let mut c = 0x11_00_00;
    loop {
        assert_eq!(char::from_u32_detailed(c),  Err(TooHigh));
        // Don't test every value. (Range.step_by() is unstable)
        match c.checked_add(0x10_11_11) {
            Some(next) => c = next,
            None => break,
        }
    }
}

#[test]
fn utf8_extra_bytes() {
    use encode_unicode::error::InvalidUtf8FirstByte::*;
    for c in 0..256 {
        assert_eq!( (c as u8).extra_utf8_bytes(), match c {
            0b_1000_0000...0b_1011_1111 => Err(ContinuationByte),
            0b_1111_1000...0b_1111_1111 => Err(TooLongSeqence),
            0b_0000_0000...0b_0111_1111 => Ok(0),
            0b_1100_0000...0b_1101_1111 => Ok(1),
            0b_1110_0000...0b_1110_1111 => Ok(2),
            0b_1111_0000...0b_1111_0111 => Ok(3),
                         _              => unreachable!(),
        });
    }
}

#[test]
fn utf16_extra_unit() {
    for c in 0..0x1_00_00 {
        assert_eq!( (c as u16).utf16_needs_extra_unit(), match c {
            0b_0000_0000_0000_0000...0b_1101_0111_1111_1111 => Ok(false),
            0b_1101_1000_0000_0000...0b_1101_1011_1111_1111 => Ok(true),
            0b_1101_1100_0000_0000...0b_1101_1111_1111_1111 => Err(InvalidUtf16FirstUnit),
            0b_1110_0000_0000_0000...0b_1111_1111_1111_1111 => Ok(false),
                                   _                        => unreachable!(),
        });
    }
}

#[test]
fn from_utf16_tuple() {
    use encode_unicode::error::InvalidUtf16Tuple::*;
    for u in 0xdc00..0xe000 {
        let close = if u%3==0 {u-100} else {u+100};
        let doesnt_matter = if u%2==0 {Some(close)} else {None};
	    assert_eq!(char::from_utf16_tuple((u,doesnt_matter)), Err(FirstIsTrailingSurrogate));
    }
    for u in (0..0xd800).chain(0xe000..0x10000) {
        assert_eq!(char::from_utf16_tuple((u as u16,Some((0x100+u) as u16))), Err(SuperfluousSecond));
	}
    for u in 0xd800..0xdc00 {
        assert_eq!(char::from_utf16_tuple((u,None)), Err(MissingSecond));

	    assert_eq!(char::from_utf16_tuple((u,Some(u - 0x2ff))), Err(InvalidSecond));
    }
}

#[test]
fn from_utf16_slice() {
    use encode_unicode::error::InvalidUtf16Slice::*;
    assert_eq!(char::from_utf16_slice(&[]), Err(EmptySlice));
    let mut buf = [0; 6];
    for u in 0xd800..0xdc00 {
        buf[0] = u;
        assert_eq!(char::from_utf16_slice(&buf[..1]), Err(MissingSecond));
        buf[1] = u;
        let pass = 2 + (u as usize % (buf.len()-2));
        assert_eq!(char::from_utf16_slice(&buf[..pass]), Err(SecondNotLowSurrogate));
    }
    for u in 0xdc00..0xe000 {
        buf[0] = u;
        let close = if u%3==0 {u-100} else {u+100};
        let pass = 1 + (u as usize % (buf.len()-1));
        buf[pass] = close;
        assert_eq!(char::from_utf16_slice(&buf[..pass]), Err(FirstLowSurrogate));
    }
}

#[test]
fn overlong_utf8() {
    use encode_unicode::error::InvalidUtf8::OverLong;
    let overlongs = [[0xc0,0xbf], [0xe0,0x9f], [0xf0,0x8f],
                     [0xc0,0x9f], [0xe0,0x8f], [0xf0,0x87]];
    for o in overlongs.iter() {
        let arr = [o[0],o[1], 0x80, 0x80];
        assert_eq!(char::from_utf8_slice(&arr), Err(InvalidUtf8Slice::Utf8(OverLong)));
        assert_eq!(char::from_utf8_array(arr), Err(InvalidUtf8Array::Utf8(OverLong)));
    }
}

#[test]
fn utf8_char_from_str() {
    use std::str::FromStr;
    use encode_unicode::error::FromStrError::*;
    assert_eq!(Utf8Char::from_str(""), Err(Empty));
    assert_eq!(Utf8Char::from_str("ab"), Err(MultipleCodepoints));
    assert_eq!(Utf8Char::from_str("́e"), Err(MultipleCodepoints));// 'e'+u301 combining mark
}
<commit_msg>Remove empty line and tabs from fail_tests.rs<commit_after>/* Copyright 2016 Torbjørn Birch Moltu
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */

//! Test that methods gives the correct error.
//! Some also test a bit more because it's easy.

use std::char;
extern crate encode_unicode;
use encode_unicode::*;
use encode_unicode::error::*;

#[test]
fn from_u32() {
    use encode_unicode::error::InvalidCodepoint::*;
    for c in 0xd800..0xe000 {
        assert_eq!(char::from_u32_detailed(c),  Err(Utf16Reserved));
    }
    let mut c = 0x11_00_00;
    loop {
        assert_eq!(char::from_u32_detailed(c),  Err(TooHigh));
        // Don't test every value. (Range.step_by() is unstable)
        match c.checked_add(0x10_11_11) {
            Some(next) => c = next,
            None => break,
        }
    }
}

#[test]
fn utf8_extra_bytes() {
    use encode_unicode::error::InvalidUtf8FirstByte::*;
    for c in 0..256 {
        assert_eq!( (c as u8).extra_utf8_bytes(), match c {
            0b_1000_0000...0b_1011_1111 => Err(ContinuationByte),
            0b_1111_1000...0b_1111_1111 => Err(TooLongSeqence),
            0b_0000_0000...0b_0111_1111 => Ok(0),
            0b_1100_0000...0b_1101_1111 => Ok(1),
            0b_1110_0000...0b_1110_1111 => Ok(2),
            0b_1111_0000...0b_1111_0111 => Ok(3),
                         _              => unreachable!(),
        });
    }
}

#[test]
fn utf16_extra_unit() {
    for c in 0..0x1_00_00 {
        assert_eq!( (c as u16).utf16_needs_extra_unit(), match c {
            0b_0000_0000_0000_0000...0b_1101_0111_1111_1111 => Ok(false),
            0b_1101_1000_0000_0000...0b_1101_1011_1111_1111 => Ok(true),
            0b_1101_1100_0000_0000...0b_1101_1111_1111_1111 => Err(InvalidUtf16FirstUnit),
            0b_1110_0000_0000_0000...0b_1111_1111_1111_1111 => Ok(false),
                                   _                        => unreachable!(),
        });
    }
}

#[test]
fn from_utf16_tuple() {
    use encode_unicode::error::InvalidUtf16Tuple::*;
    for u in 0xdc00..0xe000 {
        let close = if u%3==0 {u-100} else {u+100};
        let doesnt_matter = if u%2==0 {Some(close)} else {None};
        assert_eq!(char::from_utf16_tuple((u,doesnt_matter)), Err(FirstIsTrailingSurrogate));
    }
    for u in (0..0xd800).chain(0xe000..0x10000) {
        assert_eq!(char::from_utf16_tuple((u as u16,Some((0x100+u) as u16))), Err(SuperfluousSecond));
    }
    for u in 0xd800..0xdc00 {
        assert_eq!(char::from_utf16_tuple((u,None)), Err(MissingSecond));
        assert_eq!(char::from_utf16_tuple((u,Some(u - 0x2ff))), Err(InvalidSecond));
    }
}

#[test]
fn from_utf16_slice() {
    use encode_unicode::error::InvalidUtf16Slice::*;
    assert_eq!(char::from_utf16_slice(&[]), Err(EmptySlice));
    let mut buf = [0; 6];
    for u in 0xd800..0xdc00 {
        buf[0] = u;
        assert_eq!(char::from_utf16_slice(&buf[..1]), Err(MissingSecond));
        buf[1] = u;
        let pass = 2 + (u as usize % (buf.len()-2));
        assert_eq!(char::from_utf16_slice(&buf[..pass]), Err(SecondNotLowSurrogate));
    }
    for u in 0xdc00..0xe000 {
        buf[0] = u;
        let close = if u%3==0 {u-100} else {u+100};
        let pass = 1 + (u as usize % (buf.len()-1));
        buf[pass] = close;
        assert_eq!(char::from_utf16_slice(&buf[..pass]), Err(FirstLowSurrogate));
    }
}

#[test]
fn overlong_utf8() {
    use encode_unicode::error::InvalidUtf8::OverLong;
    let overlongs = [[0xc0,0xbf], [0xe0,0x9f], [0xf0,0x8f],
                     [0xc0,0x9f], [0xe0,0x8f], [0xf0,0x87]];
    for o in overlongs.iter() {
        let arr = [o[0],o[1], 0x80, 0x80];
        assert_eq!(char::from_utf8_slice(&arr), Err(InvalidUtf8Slice::Utf8(OverLong)));
        assert_eq!(char::from_utf8_array(arr), Err(InvalidUtf8Array::Utf8(OverLong)));
    }
}

#[test]
fn utf8_char_from_str() {
    use std::str::FromStr;
    use encode_unicode::error::FromStrError::*;
    assert_eq!(Utf8Char::from_str(""), Err(Empty));
    assert_eq!(Utf8Char::from_str("ab"), Err(MultipleCodepoints));
    assert_eq!(Utf8Char::from_str("́e"), Err(MultipleCodepoints));// 'e'+u301 combining mark
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nickel;
extern crate multipart;

use std::fs::File;
use std::io::Read;
use multipart::server::{Entries, Multipart, SaveResult};
use nickel::{HttpRouter, MiddlewareResult, Nickel, Request, Response};

fn handle_multipart<'mw>(req: &mut Request, mut res: Response<'mw>) -> MiddlewareResult<'mw> {
    match Multipart::from_request(req) {
        Ok(mut multipart) => {
            match multipart.save_all() {
                SaveResult::Full(entries) => process_entries(res, entries),

                SaveResult::Partial(entries, e) => {
                    println!("Partial errors ... {:?}", e);
                    return process_entries(res, entries);
                },

                SaveResult::Error(e) => {
                    println!("There are errors in multipart POSTing ... {:?}", e);
                    res.set(nickel::status::StatusCode::InternalServerError);
                    return res.send(format!("Server could not handle multipart POST! {:?}", e));
                },
            }
        }
        Err(_) => {
            res.set(nickel::status::StatusCode::BadRequest);
            return res.send("Request seems not was a multipart request")
        }
    }
}

/// Processes saved entries from multipart request.
/// Returns an OK response or an error.
fn process_entries<'mw>(res: Response<'mw>, entries: Entries) -> MiddlewareResult<'mw> {
    for (name, field) in entries.fields {
        println!(r#"Field "{}": "{}""#, name, field);
    }

    for (name, savedfile) in entries.files {
        let filename = match savedfile.filename {
            Some(s) => s,
            None => "None".into(),
        };

        match File::open(savedfile.path) {
            Ok(mut file) => {
                let mut contents = String::new();
                match file.read_to_string(&mut contents) {
                    Ok(sz) => println!("File: \"{}\" is of size: {}b.", filename, sz),
                    Err(e) => println!("Could not read file's \"{}\" size. Error: {:?}", filename, e),
                }
                println!(r#"Field "{}" is file "{}":"#, name, filename);
                println!("{}", contents);
                file
            }
            Err(e) => {
                println!("Could open file \"{}\". Error: {:?}", filename, e);
                return res.error(nickel::status::StatusCode::BadRequest, "The uploaded file was not readable")
            }
        };
    }

    res.send("Ok")
}

fn main() {
    let mut srv = Nickel::new();

    srv.post("/multipart_upload/", handle_multipart);

    // Start this example via:
    //
    // `cargo run --example nickel --features nickel`
    //
    // And - if you are in the root of this repository - do an example
    // upload via:
    //
    // `curl -F file=@LICENSE 'http://localhost:6868/multipart_upload/'`
    srv.listen("127.0.0.1:6868");
}
<commit_msg>Fix unused result in nickel example<commit_after>#[macro_use]
extern crate nickel;
extern crate multipart;

use std::fs::File;
use std::io::Read;
use multipart::server::{Entries, Multipart, SaveResult};
use nickel::{HttpRouter, MiddlewareResult, Nickel, Request, Response};

fn handle_multipart<'mw>(req: &mut Request, mut res: Response<'mw>) -> MiddlewareResult<'mw> {
    match Multipart::from_request(req) {
        Ok(mut multipart) => {
            match multipart.save_all() {
                SaveResult::Full(entries) => process_entries(res, entries),

                SaveResult::Partial(entries, e) => {
                    println!("Partial errors ... {:?}", e);
                    return process_entries(res, entries);
                },

                SaveResult::Error(e) => {
                    println!("There are errors in multipart POSTing ... {:?}", e);
                    res.set(nickel::status::StatusCode::InternalServerError);
                    return res.send(format!("Server could not handle multipart POST! {:?}", e));
                },
            }
        }
        Err(_) => {
            res.set(nickel::status::StatusCode::BadRequest);
            return res.send("Request seems not was a multipart request")
        }
    }
}

/// Processes saved entries from multipart request.
/// Returns an OK response or an error.
fn process_entries<'mw>(res: Response<'mw>, entries: Entries) -> MiddlewareResult<'mw> {
    for (name, field) in entries.fields {
        println!(r#"Field "{}": "{}""#, name, field);
    }

    for (name, savedfile) in entries.files {
        let filename = match savedfile.filename {
            Some(s) => s,
            None => "None".into(),
        };

        match File::open(savedfile.path) {
            Ok(mut file) => {
                let mut contents = String::new();
                match file.read_to_string(&mut contents) {
                    Ok(sz) => println!("File: \"{}\" is of size: {}b.", filename, sz),
                    Err(e) => println!("Could not read file's \"{}\" size. Error: {:?}", filename, e),
                }
                println!(r#"Field "{}" is file "{}":"#, name, filename);
                println!("{}", contents);
                file
            }
            Err(e) => {
                println!("Could open file \"{}\". Error: {:?}", filename, e);
                return res.error(nickel::status::StatusCode::BadRequest, "The uploaded file was not readable")
            }
        };
    }

    res.send("Ok")
}

fn main() {
    let mut srv = Nickel::new();

    srv.post("/multipart_upload/", handle_multipart);

    // Start this example via:
    //
    // `cargo run --example nickel --features nickel`
    //
    // And - if you are in the root of this repository - do an example
    // upload via:
    //
    // `curl -F file=@LICENSE 'http://localhost:6868/multipart_upload/'`
    srv.listen("127.0.0.1:6868").expect("Failed to bind server");
}
<|endoftext|>


<commit_before>use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions};

pub fn opts() -> TargetOptions {
    let mut pre_link_args = LinkArgs::new();
    pre_link_args.insert(
        LinkerFlavor::Lld(LldFlavor::Ld),
        vec!["--build-id".to_string(), "--hash-style=gnu".to_string(), "--Bstatic".to_string()],
    );

    TargetOptions {
        os: "hermit".to_string(),
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
        disable_redzone: true,
        linker: Some("rust-lld".to_owned()),
        executables: true,
        pre_link_args,
        panic_strategy: PanicStrategy::Abort,
        position_independent_executables: true,
        static_position_independent_executables: true,
        ..Default::default()
    }
}
<commit_msg>Rollup merge of #90404 - mkroening:hermit-kernel-no-os, r=joshtriplett<commit_after>use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions};

pub fn opts() -> TargetOptions {
    let mut pre_link_args = LinkArgs::new();
    pre_link_args.insert(
        LinkerFlavor::Lld(LldFlavor::Ld),
        vec!["--build-id".to_string(), "--hash-style=gnu".to_string(), "--Bstatic".to_string()],
    );

    TargetOptions {
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
        disable_redzone: true,
        linker: Some("rust-lld".to_owned()),
        executables: true,
        pre_link_args,
        panic_strategy: PanicStrategy::Abort,
        position_independent_executables: true,
        static_position_independent_executables: true,
        ..Default::default()
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]

//! Making sure that no warning is generated by code from generate_gl_bindings!
#![deny(ctypes)]
#![deny(dead_code)]
#![deny(non_snake_case)]
#![deny(unused_variable)]

#[phase(plugin)]
extern crate gl_generator;

extern crate libc;

mod gl_global {
    generate_gl_bindings!("gl", "core", "4.5", "global")
}

mod gl_static {
    generate_gl_bindings!("gl", "core", "4.5", "static")
}

mod gl_struct {
    generate_gl_bindings!("gl", "core", "4.5", "struct")
}

mod glx_global {
    generate_gl_bindings!("glx", "core", "1.4", "global")
}

mod glx_static {
    generate_gl_bindings!("glx", "core", "1.4", "static")
}

mod glx_struct {
    generate_gl_bindings!("glx", "core", "1.4", "struct")
}

mod wgl_global {
    generate_gl_bindings!("wgl", "core", "1.0", "global")
}

mod wgl_static {
    generate_gl_bindings!("wgl", "core", "1.0", "static")
}

mod wgl_struct {
    generate_gl_bindings!("wgl", "core", "1.0", "struct")
}

mod egl_global {
    use libc;

    #[allow(non_camel_case_types)]
    pub type khronos_utime_nanoseconds_t = libc::c_int;
    #[allow(non_camel_case_types)]
    pub type khronos_uint64_t = libc::uint64_t;
    #[allow(non_camel_case_types)]
    pub type khronos_ssize_t = libc::ssize_t;
    pub type EGLNativeDisplayType = *const libc::c_void;
    pub type EGLNativePixmapType = *const libc::c_void;
    pub type EGLNativeWindowType = *const libc::c_void;
    pub type EGLint = libc::c_int;
    pub type NativeDisplayType = *const libc::c_void;
    pub type NativePixmapType = *const libc::c_void;
    pub type NativeWindowType = *const libc::c_void;

    generate_gl_bindings!("egl", "core", "1.5", "global")
}

mod egl_static {
    use libc;

    #[allow(non_camel_case_types)]
    pub type khronos_utime_nanoseconds_t = libc::c_int;
    #[allow(non_camel_case_types)]
    pub type khronos_uint64_t = libc::uint64_t;
    #[allow(non_camel_case_types)]
    pub type khronos_ssize_t = libc::ssize_t;
    pub type EGLNativeDisplayType = *const libc::c_void;
    pub type EGLNativePixmapType = *const libc::c_void;
    pub type EGLNativeWindowType = *const libc::c_void;
    pub type EGLint = libc::c_int;
    pub type NativeDisplayType = *const libc::c_void;
    pub type NativePixmapType = *const libc::c_void;
    pub type NativeWindowType = *const libc::c_void;

    generate_gl_bindings!("egl", "core", "1.5", "static")
}

mod egl_struct {
    use libc;

    #[allow(non_camel_case_types)]
    pub type khronos_utime_nanoseconds_t = libc::c_int;
    #[allow(non_camel_case_types)]
    pub type khronos_uint64_t = libc::uint64_t;
    #[allow(non_camel_case_types)]
    pub type khronos_ssize_t = libc::ssize_t;
    pub type EGLNativeDisplayType = *const libc::c_void;
    pub type EGLNativePixmapType = *const libc::c_void;
    pub type EGLNativeWindowType = *const libc::c_void;
    pub type EGLint = libc::c_int;
    pub type NativeDisplayType = *const libc::c_void;
    pub type NativePixmapType = *const libc::c_void;
    pub type NativeWindowType = *const libc::c_void;

    generate_gl_bindings!("egl", "core", "1.5", "struct")
}

mod gles1_global {
    generate_gl_bindings!("gles1", "core", "1.1", "global")
}

mod gles1_static {
    generate_gl_bindings!("gles1", "core", "1.1", "static")
}

mod gles1_struct {
    generate_gl_bindings!("gles1", "core", "1.1", "struct")
}

mod gles2_global {
    generate_gl_bindings!("gles2", "core", "3.1", "global")
}

mod gles2_static {
    generate_gl_bindings!("gles2", "core", "3.1", "static")
}

mod gles2_struct {
    generate_gl_bindings!("gles2", "core", "3.1", "struct")
}
<commit_msg>Replace the #[deny(...)] by #![deny(warnings)] in no_warnings.rs<commit_after>#![feature(phase)]

//! Making sure that no warning is generated by code from generate_gl_bindings!
#![deny(warnings)]

#[phase(plugin)]
extern crate gl_generator;

extern crate libc;

mod gl_global {
    generate_gl_bindings!("gl", "core", "4.5", "global")
}

mod gl_static {
    generate_gl_bindings!("gl", "core", "4.5", "static")
}

mod gl_struct {
    generate_gl_bindings!("gl", "core", "4.5", "struct")
}

mod glx_global {
    generate_gl_bindings!("glx", "core", "1.4", "global")
}

mod glx_static {
    generate_gl_bindings!("glx", "core", "1.4", "static")
}

mod glx_struct {
    generate_gl_bindings!("glx", "core", "1.4", "struct")
}

mod wgl_global {
    generate_gl_bindings!("wgl", "core", "1.0", "global")
}

mod wgl_static {
    generate_gl_bindings!("wgl", "core", "1.0", "static")
}

mod wgl_struct {
    generate_gl_bindings!("wgl", "core", "1.0", "struct")
}

mod egl_global {
    use libc;

    #[allow(non_camel_case_types)]
    pub type khronos_utime_nanoseconds_t = libc::c_int;
    #[allow(non_camel_case_types)]
    pub type khronos_uint64_t = libc::uint64_t;
    #[allow(non_camel_case_types)]
    pub type khronos_ssize_t = libc::ssize_t;
    pub type EGLNativeDisplayType = *const libc::c_void;
    pub type EGLNativePixmapType = *const libc::c_void;
    pub type EGLNativeWindowType = *const libc::c_void;
    pub type EGLint = libc::c_int;
    pub type NativeDisplayType = *const libc::c_void;
    pub type NativePixmapType = *const libc::c_void;
    pub type NativeWindowType = *const libc::c_void;

    generate_gl_bindings!("egl", "core", "1.5", "global")
}

mod egl_static {
    use libc;

    #[allow(non_camel_case_types)]
    pub type khronos_utime_nanoseconds_t = libc::c_int;
    #[allow(non_camel_case_types)]
    pub type khronos_uint64_t = libc::uint64_t;
    #[allow(non_camel_case_types)]
    pub type khronos_ssize_t = libc::ssize_t;
    pub type EGLNativeDisplayType = *const libc::c_void;
    pub type EGLNativePixmapType = *const libc::c_void;
    pub type EGLNativeWindowType = *const libc::c_void;
    pub type EGLint = libc::c_int;
    pub type NativeDisplayType = *const libc::c_void;
    pub type NativePixmapType = *const libc::c_void;
    pub type NativeWindowType = *const libc::c_void;

    generate_gl_bindings!("egl", "core", "1.5", "static")
}

mod egl_struct {
    use libc;

    #[allow(non_camel_case_types)]
    pub type khronos_utime_nanoseconds_t = libc::c_int;
    #[allow(non_camel_case_types)]
    pub type khronos_uint64_t = libc::uint64_t;
    #[allow(non_camel_case_types)]
    pub type khronos_ssize_t = libc::ssize_t;
    pub type EGLNativeDisplayType = *const libc::c_void;
    pub type EGLNativePixmapType = *const libc::c_void;
    pub type EGLNativeWindowType = *const libc::c_void;
    pub type EGLint = libc::c_int;
    pub type NativeDisplayType = *const libc::c_void;
    pub type NativePixmapType = *const libc::c_void;
    pub type NativeWindowType = *const libc::c_void;

    generate_gl_bindings!("egl", "core", "1.5", "struct")
}

mod gles1_global {
    generate_gl_bindings!("gles1", "core", "1.1", "global")
}

mod gles1_static {
    generate_gl_bindings!("gles1", "core", "1.1", "static")
}

mod gles1_struct {
    generate_gl_bindings!("gles1", "core", "1.1", "struct")
}

mod gles2_global {
    generate_gl_bindings!("gles2", "core", "3.1", "global")
}

mod gles2_static {
    generate_gl_bindings!("gles2", "core", "3.1", "static")
}

mod gles2_struct {
    generate_gl_bindings!("gles2", "core", "3.1", "struct")
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager

#![deny(dead_code)]

struct Struct<T> {
    x: T,
    f: fn(x: T) -> T,
}

fn id<T>(x: T) -> T { x }

impl<T> Struct<T> {

    fn new(x: T) -> Struct<T> {
        Struct {
            x: x,
            f: id
        }
    }

    fn get<T2>(self, x: T2) -> (T, T2) {
        (self.x, x)
    }
}

pub struct LifeTimeOnly<'a> {
    _a: &'a u32
}

impl<'a> LifeTimeOnly<'a> {

    //~ TRANS_ITEM fn generic_impl::{{impl}}[1]::foo[0]
    pub fn foo(&self) {}
    //~ TRANS_ITEM fn generic_impl::{{impl}}[1]::bar[0]
    pub fn bar(&'a self) {}
    //~ TRANS_ITEM fn generic_impl::{{impl}}[1]::baz[0]
    pub fn baz<'b>(&'b self) {}

    pub fn non_instantiated<T>(&self) {}
}

//~ TRANS_ITEM fn generic_impl::main[0]
fn main() {
    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<i32>
    //~ TRANS_ITEM fn generic_impl::id[0]<i32>
    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<i32, i16>
    let _ = Struct::new(0i32).get(0i16);

    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<i64>
    //~ TRANS_ITEM fn generic_impl::id[0]<i64>
    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<i64, i16>
    let _ = Struct::new(0i64).get(0i16);

    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<char>
    //~ TRANS_ITEM fn generic_impl::id[0]<char>
    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<char, i16>
    let _ = Struct::new('c').get(0i16);

    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<&str>
    //~ TRANS_ITEM fn generic_impl::id[0]<&str>
    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<generic_impl::Struct[0]<&str>, i16>
    let _ = Struct::new(Struct::new("str")).get(0i16);

    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<generic_impl::Struct[0]<&str>>
    //~ TRANS_ITEM fn generic_impl::id[0]<generic_impl::Struct[0]<&str>>
    let _ = (Struct::new(Struct::new("str")).f)(Struct::new("str"));
}

//~ TRANS_ITEM drop-glue i8
<commit_msg>fix codegen-units fallout<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager

#![deny(dead_code)]

struct Struct<T> {
    x: T,
    f: fn(x: T) -> T,
}

fn id<T>(x: T) -> T { x }

impl<T> Struct<T> {

    fn new(x: T) -> Struct<T> {
        Struct {
            x: x,
            f: id
        }
    }

    fn get<T2>(self, x: T2) -> (T, T2) {
        (self.x, x)
    }
}

pub struct LifeTimeOnly<'a> {
    _a: &'a u32
}

impl<'a> LifeTimeOnly<'a> {

    //~ TRANS_ITEM fn generic_impl::{{impl}}[1]::foo[0]
    pub fn foo(&self) {}
    //~ TRANS_ITEM fn generic_impl::{{impl}}[1]::bar[0]
    pub fn bar(&'a self) {}
    //~ TRANS_ITEM fn generic_impl::{{impl}}[1]::baz[0]
    pub fn baz<'b>(&'b self) {}

    pub fn non_instantiated<T>(&self) {}
}

//~ TRANS_ITEM fn generic_impl::main[0]
fn main() {
    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<i32>
    //~ TRANS_ITEM fn generic_impl::id[0]<i32>
    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<i32, i16>
    let _ = Struct::new(0i32).get(0i16);

    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<i64>
    //~ TRANS_ITEM fn generic_impl::id[0]<i64>
    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<i64, i16>
    let _ = Struct::new(0i64).get(0i16);

    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<char>
    //~ TRANS_ITEM fn generic_impl::id[0]<char>
    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<char, i16>
    let _ = Struct::new('c').get(0i16);

    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<&str>
    //~ TRANS_ITEM fn generic_impl::id[0]<&str>
    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<generic_impl::Struct[0]<&str>, i16>
    let _ = Struct::new(Struct::new("str")).get(0i16);

    //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<generic_impl::Struct[0]<&str>>
    //~ TRANS_ITEM fn generic_impl::id[0]<generic_impl::Struct[0]<&str>>
    let _ = (Struct::new(Struct::new("str")).f)(Struct::new("str"));
}
<|endoftext|>


<commit_before>extern crate spaceapi_server;

use spaceapi_server::SpaceapiServerBuilder;
use spaceapi_server::api;
use spaceapi_server::modifiers;

fn main() {

    // Create new minimal Status instance
    let status = api::StatusBuilder::new("coredump")
        .logo("https://www.coredump.ch/logo.png")
        .url("https://www.coredump.ch/")
        .location(api::Location {
            address: Some("Spinnereistrasse 2, 8640 Rapperswil, Switzerland".into()),
            lat: 47.22936,
            lon: 8.82949,
        })
        .contact(api::Contact {
            irc: Some("irc://freenode.net/#coredump".into()),
            twitter: Some("@coredump_ch".into()),
            ..Default::default()
        })
        .add_issue_report_channel("email")
        .add_issue_report_channel("twitter")
        .build()
        .expect("Creating status failed");

    // Set up server
    let server = SpaceapiServerBuilder::new(status)
        .redis_connection_info("redis://127.0.0.1/")
        .build()
        .unwrap();

    // Serve!
    let _ = server.serve("127.0.0.1:8000");
}
<commit_msg>Fix unused import warning (#71)<commit_after>extern crate spaceapi_server;

use spaceapi_server::SpaceapiServerBuilder;
use spaceapi_server::api;

fn main() {

    // Create new minimal Status instance
    let status = api::StatusBuilder::new("coredump")
        .logo("https://www.coredump.ch/logo.png")
        .url("https://www.coredump.ch/")
        .location(api::Location {
            address: Some("Spinnereistrasse 2, 8640 Rapperswil, Switzerland".into()),
            lat: 47.22936,
            lon: 8.82949,
        })
        .contact(api::Contact {
            irc: Some("irc://freenode.net/#coredump".into()),
            twitter: Some("@coredump_ch".into()),
            ..Default::default()
        })
        .add_issue_report_channel("email")
        .add_issue_report_channel("twitter")
        .build()
        .expect("Creating status failed");

    // Set up server
    let server = SpaceapiServerBuilder::new(status)
        .redis_connection_info("redis://127.0.0.1/")
        .build()
        .unwrap();

    // Serve!
    let _ = server.serve("127.0.0.1:8000");
}
<|endoftext|>


<commit_before>// This lint claims ugly casting is somehow safer than transmute, but there's
// no evidence that is the case. Shush.
#![allow(clippy::transmute_ptr_to_ptr)]

use std::fmt;
use std::mem::{self, MaybeUninit};

/// A wrapper around a byte buffer that is incrementally filled and initialized.
///
/// This type is a sort of "double cursor". It tracks three regions in the
/// buffer: a region at the beginning of the buffer that has been logically
/// filled with data, a region that has been initialized at some point but not
/// yet logically filled, and a region at the end that may be uninitialized.
/// The filled region is guaranteed to be a subset of the initialized region.
///
/// In summary, the contents of the buffer can be visualized as:
///
/// ```not_rust
/// [             capacity              ]
/// [ filled |         unfilled         ]
/// [    initialized    | uninitialized ]
/// ```
///
/// It is undefined behavior to de-initialize any bytes from the uninitialized
/// region, since it is merely unknown whether this region is uninitialized or
/// not, and if part of it turns out to be initialized, it must stay initialized.
pub struct ReadBuf<'a> {
    buf: &'a mut [MaybeUninit<u8>],
    filled: usize,
    initialized: usize,
}

impl<'a> ReadBuf<'a> {
    /// Creates a new `ReadBuf` from a fully initialized buffer.
    #[inline]
    pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a> {
        let initialized = buf.len();
        let buf = unsafe { mem::transmute::<&mut [u8], &mut [MaybeUninit<u8>]>(buf) };
        ReadBuf {
            buf,
            filled: 0,
            initialized,
        }
    }

    /// Creates a new `ReadBuf` from a fully uninitialized buffer.
    ///
    /// Use `assume_init` if part of the buffer is known to be already inintialized.
    #[inline]
    pub fn uninit(buf: &'a mut [MaybeUninit<u8>]) -> ReadBuf<'a> {
        ReadBuf {
            buf,
            filled: 0,
            initialized: 0,
        }
    }

    /// Returns the total capacity of the buffer.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.buf.len()
    }

    /// Returns a shared reference to the filled portion of the buffer.
    #[inline]
    pub fn filled(&self) -> &[u8] {
        let slice = &self.buf[..self.filled];
        // safety: filled describes how far into the buffer that the
        // user has filled with bytes, so it's been initialized.
        // TODO: This could use `MaybeUninit::slice_get_ref` when it is stable.
        unsafe { mem::transmute::<&[MaybeUninit<u8>], &[u8]>(slice) }
    }

    /// Returns a mutable reference to the filled portion of the buffer.
    #[inline]
    pub fn filled_mut(&mut self) -> &mut [u8] {
        let slice = &mut self.buf[..self.filled];
        // safety: filled describes how far into the buffer that the
        // user has filled with bytes, so it's been initialized.
        // TODO: This could use `MaybeUninit::slice_get_mut` when it is stable.
        unsafe { mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(slice) }
    }

    /// Returns a new `ReadBuf` comprised of the unfilled section up to `n`.
    #[inline]
    pub fn take(&mut self, n: usize) -> ReadBuf<'_> {
        let max = std::cmp::min(self.remaining(), n);
        // Saftey: We don't set any of the `unfilled_mut` with `MaybeUninit::uninit`.
        unsafe { ReadBuf::uninit(&mut self.unfilled_mut()[..max]) }
    }

    /// Returns a shared reference to the initialized portion of the buffer.
    ///
    /// This includes the filled portion.
    #[inline]
    pub fn initialized(&self) -> &[u8] {
        let slice = &self.buf[..self.initialized];
        // safety: initialized describes how far into the buffer that the
        // user has at some point initialized with bytes.
        // TODO: This could use `MaybeUninit::slice_get_ref` when it is stable.
        unsafe { mem::transmute::<&[MaybeUninit<u8>], &[u8]>(slice) }
    }

    /// Returns a mutable reference to the initialized portion of the buffer.
    ///
    /// This includes the filled portion.
    #[inline]
    pub fn initialized_mut(&mut self) -> &mut [u8] {
        let slice = &mut self.buf[..self.initialized];
        // safety: initialized describes how far into the buffer that the
        // user has at some point initialized with bytes.
        // TODO: This could use `MaybeUninit::slice_get_mut` when it is stable.
        unsafe { mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(slice) }
    }

    /// Returns a mutable reference to the unfilled part of the buffer without ensuring that it has been fully
    /// initialized.
    ///
    /// # Safety
    ///
    /// The caller must not de-initialize portions of the buffer that have already been initialized.
    /// This includes any bytes in the region marked as uninitialized by `ReadBuf`.
    #[inline]
    pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit<u8>] {
        &mut self.buf[self.filled..]
    }

    /// Returns a mutable reference to the unfilled part of the buffer, ensuring it is fully initialized.
    ///
    /// Since `ReadBuf` tracks the region of the buffer that has been initialized, this is effectively "free" after
    /// the first use.
    #[inline]
    pub fn initialize_unfilled(&mut self) -> &mut [u8] {
        self.initialize_unfilled_to(self.remaining())
    }

    /// Returns a mutable reference to the first `n` bytes of the unfilled part of the buffer, ensuring it is
    /// fully initialized.
    ///
    /// # Panics
    ///
    /// Panics if `self.remaining()` is less than `n`.
    #[inline]
    pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] {
        assert!(self.remaining() >= n, "n overflows remaining");

        // This can't overflow, otherwise the assert above would have failed.
        let end = self.filled + n;

        if self.initialized < end {
            unsafe {
                self.buf[self.initialized..end]
                    .as_mut_ptr()
                    .write_bytes(0, end - self.initialized);
            }
            self.initialized = end;
        }

        let slice = &mut self.buf[self.filled..end];
        // safety: just above, we checked that the end of the buf has
        // been initialized to some value.
        unsafe { mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(slice) }
    }

    /// Returns the number of bytes at the end of the slice that have not yet been filled.
    #[inline]
    pub fn remaining(&self) -> usize {
        self.capacity() - self.filled
    }

    /// Clears the buffer, resetting the filled region to empty.
    ///
    /// The number of initialized bytes is not changed, and the contents of the buffer are not modified.
    #[inline]
    pub fn clear(&mut self) {
        self.filled = 0;
    }

    /// Advances the size of the filled region of the buffer.
    ///
    /// The number of initialized bytes is not changed.
    ///
    /// # Panics
    ///
    /// Panics if the filled region of the buffer would become larger than the initialized region.
    #[inline]
    pub fn advance(&mut self, n: usize) {
        let new = self.filled.checked_add(n).expect("filled overflow");
        self.set_filled(new);
    }

    /// Sets the size of the filled region of the buffer.
    ///
    /// The number of initialized bytes is not changed.
    ///
    /// Note that this can be used to *shrink* the filled region of the buffer in addition to growing it (for
    /// example, by a `AsyncRead` implementation that compresses data in-place).
    ///
    /// # Panics
    ///
    /// Panics if the filled region of the buffer would become larger than the intialized region.
    #[inline]
    pub fn set_filled(&mut self, n: usize) {
        assert!(
            n <= self.initialized,
            "filled must not become larger than initialized"
        );
        self.filled = n;
    }

    /// Asserts that the first `n` unfilled bytes of the buffer are initialized.
    ///
    /// `ReadBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer
    /// bytes than are already known to be initialized.
    ///
    /// # Safety
    ///
    /// The caller must ensure that `n` unfilled bytes of the buffer have already been initialized.
    #[inline]
    pub unsafe fn assume_init(&mut self, n: usize) {
        let new = self.filled + n;
        if new > self.initialized {
            self.initialized = new;
        }
    }

    /// Appends data to the buffer, advancing the written position and possibly also the initialized position.
    ///
    /// # Panics
    ///
    /// Panics if `self.remaining()` is less than `buf.len()`.
    #[inline]
    pub fn put_slice(&mut self, buf: &[u8]) {
        assert!(
            self.remaining() >= buf.len(),
            "buf.len() must fit in remaining()"
        );

        let amt = buf.len();
        // Cannot overflow, asserted above
        let end = self.filled + amt;

        // Safety: the length is asserted above
        unsafe {
            self.buf[self.filled..end]
                .as_mut_ptr()
                .cast::<u8>()
                .copy_from_nonoverlapping(buf.as_ptr(), amt);
        }

        if self.initialized < end {
            self.initialized = end;
        }
        self.filled = end;
    }
}

impl fmt::Debug for ReadBuf<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("ReadBuf")
            .field("filled", &self.filled)
            .field("initialized", &self.initialized)
            .field("capacity", &self.capacity())
            .finish()
    }
}
<commit_msg>io: add ReadBuf::inner_mut (#3443)<commit_after>// This lint claims ugly casting is somehow safer than transmute, but there's
// no evidence that is the case. Shush.
#![allow(clippy::transmute_ptr_to_ptr)]

use std::fmt;
use std::mem::{self, MaybeUninit};

/// A wrapper around a byte buffer that is incrementally filled and initialized.
///
/// This type is a sort of "double cursor". It tracks three regions in the
/// buffer: a region at the beginning of the buffer that has been logically
/// filled with data, a region that has been initialized at some point but not
/// yet logically filled, and a region at the end that may be uninitialized.
/// The filled region is guaranteed to be a subset of the initialized region.
///
/// In summary, the contents of the buffer can be visualized as:
///
/// ```not_rust
/// [             capacity              ]
/// [ filled |         unfilled         ]
/// [    initialized    | uninitialized ]
/// ```
///
/// It is undefined behavior to de-initialize any bytes from the uninitialized
/// region, since it is merely unknown whether this region is uninitialized or
/// not, and if part of it turns out to be initialized, it must stay initialized.
pub struct ReadBuf<'a> {
    buf: &'a mut [MaybeUninit<u8>],
    filled: usize,
    initialized: usize,
}

impl<'a> ReadBuf<'a> {
    /// Creates a new `ReadBuf` from a fully initialized buffer.
    #[inline]
    pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a> {
        let initialized = buf.len();
        let buf = unsafe { mem::transmute::<&mut [u8], &mut [MaybeUninit<u8>]>(buf) };
        ReadBuf {
            buf,
            filled: 0,
            initialized,
        }
    }

    /// Creates a new `ReadBuf` from a fully uninitialized buffer.
    ///
    /// Use `assume_init` if part of the buffer is known to be already inintialized.
    #[inline]
    pub fn uninit(buf: &'a mut [MaybeUninit<u8>]) -> ReadBuf<'a> {
        ReadBuf {
            buf,
            filled: 0,
            initialized: 0,
        }
    }

    /// Returns the total capacity of the buffer.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.buf.len()
    }

    /// Returns a shared reference to the filled portion of the buffer.
    #[inline]
    pub fn filled(&self) -> &[u8] {
        let slice = &self.buf[..self.filled];
        // safety: filled describes how far into the buffer that the
        // user has filled with bytes, so it's been initialized.
        // TODO: This could use `MaybeUninit::slice_get_ref` when it is stable.
        unsafe { mem::transmute::<&[MaybeUninit<u8>], &[u8]>(slice) }
    }

    /// Returns a mutable reference to the filled portion of the buffer.
    #[inline]
    pub fn filled_mut(&mut self) -> &mut [u8] {
        let slice = &mut self.buf[..self.filled];
        // safety: filled describes how far into the buffer that the
        // user has filled with bytes, so it's been initialized.
        // TODO: This could use `MaybeUninit::slice_get_mut` when it is stable.
        unsafe { mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(slice) }
    }

    /// Returns a new `ReadBuf` comprised of the unfilled section up to `n`.
    #[inline]
    pub fn take(&mut self, n: usize) -> ReadBuf<'_> {
        let max = std::cmp::min(self.remaining(), n);
        // Saftey: We don't set any of the `unfilled_mut` with `MaybeUninit::uninit`.
        unsafe { ReadBuf::uninit(&mut self.unfilled_mut()[..max]) }
    }

    /// Returns a shared reference to the initialized portion of the buffer.
    ///
    /// This includes the filled portion.
    #[inline]
    pub fn initialized(&self) -> &[u8] {
        let slice = &self.buf[..self.initialized];
        // safety: initialized describes how far into the buffer that the
        // user has at some point initialized with bytes.
        // TODO: This could use `MaybeUninit::slice_get_ref` when it is stable.
        unsafe { mem::transmute::<&[MaybeUninit<u8>], &[u8]>(slice) }
    }

    /// Returns a mutable reference to the initialized portion of the buffer.
    ///
    /// This includes the filled portion.
    #[inline]
    pub fn initialized_mut(&mut self) -> &mut [u8] {
        let slice = &mut self.buf[..self.initialized];
        // safety: initialized describes how far into the buffer that the
        // user has at some point initialized with bytes.
        // TODO: This could use `MaybeUninit::slice_get_mut` when it is stable.
        unsafe { mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(slice) }
    }

    /// Returns a mutable reference to the entire buffer, without ensuring that it has been fully
    /// initialized.
    ///
    /// The elements between 0 and `self.filled().len()` are filled, and those between 0 and
    /// `self.initialized().len()` are initialized (and so can be transmuted to a `&mut [u8]`).
    ///
    /// The caller of this method must ensure that these invariants are upheld. For example, if the
    /// caller initializes some of the uninitialized section of the buffer, it must call
    /// [`assume_init`](Self::assume_init) with the number of bytes initialized.
    ///
    /// # Safety
    ///
    /// The caller must not de-initialize portions of the buffer that have already been initialized.
    /// This includes any bytes in the region marked as uninitialized by `ReadBuf`.
    #[inline]
    pub unsafe fn inner_mut(&mut self) -> &mut [MaybeUninit<u8>] {
        self.buf
    }

    /// Returns a mutable reference to the unfilled part of the buffer without ensuring that it has been fully
    /// initialized.
    ///
    /// # Safety
    ///
    /// The caller must not de-initialize portions of the buffer that have already been initialized.
    /// This includes any bytes in the region marked as uninitialized by `ReadBuf`.
    #[inline]
    pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit<u8>] {
        &mut self.buf[self.filled..]
    }

    /// Returns a mutable reference to the unfilled part of the buffer, ensuring it is fully initialized.
    ///
    /// Since `ReadBuf` tracks the region of the buffer that has been initialized, this is effectively "free" after
    /// the first use.
    #[inline]
    pub fn initialize_unfilled(&mut self) -> &mut [u8] {
        self.initialize_unfilled_to(self.remaining())
    }

    /// Returns a mutable reference to the first `n` bytes of the unfilled part of the buffer, ensuring it is
    /// fully initialized.
    ///
    /// # Panics
    ///
    /// Panics if `self.remaining()` is less than `n`.
    #[inline]
    pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] {
        assert!(self.remaining() >= n, "n overflows remaining");

        // This can't overflow, otherwise the assert above would have failed.
        let end = self.filled + n;

        if self.initialized < end {
            unsafe {
                self.buf[self.initialized..end]
                    .as_mut_ptr()
                    .write_bytes(0, end - self.initialized);
            }
            self.initialized = end;
        }

        let slice = &mut self.buf[self.filled..end];
        // safety: just above, we checked that the end of the buf has
        // been initialized to some value.
        unsafe { mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(slice) }
    }

    /// Returns the number of bytes at the end of the slice that have not yet been filled.
    #[inline]
    pub fn remaining(&self) -> usize {
        self.capacity() - self.filled
    }

    /// Clears the buffer, resetting the filled region to empty.
    ///
    /// The number of initialized bytes is not changed, and the contents of the buffer are not modified.
    #[inline]
    pub fn clear(&mut self) {
        self.filled = 0;
    }

    /// Advances the size of the filled region of the buffer.
    ///
    /// The number of initialized bytes is not changed.
    ///
    /// # Panics
    ///
    /// Panics if the filled region of the buffer would become larger than the initialized region.
    #[inline]
    pub fn advance(&mut self, n: usize) {
        let new = self.filled.checked_add(n).expect("filled overflow");
        self.set_filled(new);
    }

    /// Sets the size of the filled region of the buffer.
    ///
    /// The number of initialized bytes is not changed.
    ///
    /// Note that this can be used to *shrink* the filled region of the buffer in addition to growing it (for
    /// example, by a `AsyncRead` implementation that compresses data in-place).
    ///
    /// # Panics
    ///
    /// Panics if the filled region of the buffer would become larger than the intialized region.
    #[inline]
    pub fn set_filled(&mut self, n: usize) {
        assert!(
            n <= self.initialized,
            "filled must not become larger than initialized"
        );
        self.filled = n;
    }

    /// Asserts that the first `n` unfilled bytes of the buffer are initialized.
    ///
    /// `ReadBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer
    /// bytes than are already known to be initialized.
    ///
    /// # Safety
    ///
    /// The caller must ensure that `n` unfilled bytes of the buffer have already been initialized.
    #[inline]
    pub unsafe fn assume_init(&mut self, n: usize) {
        let new = self.filled + n;
        if new > self.initialized {
            self.initialized = new;
        }
    }

    /// Appends data to the buffer, advancing the written position and possibly also the initialized position.
    ///
    /// # Panics
    ///
    /// Panics if `self.remaining()` is less than `buf.len()`.
    #[inline]
    pub fn put_slice(&mut self, buf: &[u8]) {
        assert!(
            self.remaining() >= buf.len(),
            "buf.len() must fit in remaining()"
        );

        let amt = buf.len();
        // Cannot overflow, asserted above
        let end = self.filled + amt;

        // Safety: the length is asserted above
        unsafe {
            self.buf[self.filled..end]
                .as_mut_ptr()
                .cast::<u8>()
                .copy_from_nonoverlapping(buf.as_ptr(), amt);
        }

        if self.initialized < end {
            self.initialized = end;
        }
        self.filled = end;
    }
}

impl fmt::Debug for ReadBuf<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("ReadBuf")
            .field("filled", &self.filled)
            .field("initialized", &self.initialized)
            .field("capacity", &self.capacity())
            .finish()
    }
}
<|endoftext|>


<commit_before>//! Defines a PolynomialCalculator with common arithmetic operations, functions
//! and constants already defined.

use super::*;
use calculator::*;
use tokenizer::Tokenizer;
use evaluator::{Evaluator, Function};
use parser::{Parser, Operator, OperatorAssociativity};
use polynomial::Polynomial;
use std::f64::consts::{PI, E};

/// PolynomialCalculator is a calculator using a PolynomialParser and a PolynomialEvaluator
/// to provide multiple default operations.
///
/// This calculator supports addition `+`, subtraction `-`, multiplication `*`,
/// division `/` and exponentiation `^` operators, `log(number, base)`,
/// `log10(number)` and `bind(polynomial, double)` functions, `x`, `inf`, `nan`
/// symbols and `pi` and `e` constants.
///
/// While usage of the calculator is the easiest way of embedding computation
/// engine into your program, please note that a Tokenizer, PolynomialParser and
/// PolynomialEvaluator is created with each call, which requires reallocation
/// of memory.
///
/// # Examples
///
/// ```
/// # use xxcalc::polynomial_calculator::PolynomialCalculator;
/// # use xxcalc::polynomial::Polynomial;
/// # use xxcalc::calculator::Calculator;
/// # use std::f64::consts::PI;
///
/// assert_eq!(PolynomialCalculator.process("2+2"), Ok(Polynomial::constant(4.0)));
/// assert_eq!(PolynomialCalculator.process("(2+2)*-2"), Ok(Polynomial::constant(-8.0)));
/// assert_eq!(String::from(PolynomialCalculator.process("(x+1)*(-0.13x^18-x^7)").unwrap()), "-0.13x^19-0.13x^18-x^8-x^7");
/// assert_eq!(PolynomialCalculator.process("bind(pi*x^2, 10)"), Ok(Polynomial::constant(PI * 10.0 * 10.0)));
/// ```
pub struct PolynomialCalculator;

impl Calculator<Tokenizer, PolynomialParser, PolynomialEvaluator> for PolynomialCalculator {

}

/// Extends Evaluator with handlers for common operators and functions.
pub struct PolynomialEvaluator {
  /// Underlying evaluator (one can use it to extend it furthermore)
  pub evaluator: Evaluator
}

/// Creates PolynomialEvaluator and extends the basic Evaluator.
///
/// Handlers for common arithmetic operations, functions and some constants
/// are registered to the underlying evaluator.
impl Default for PolynomialEvaluator {
  fn default() -> PolynomialEvaluator {
    let mut evaluator = Evaluator::default();

    evaluator.register_constant("x", Polynomial::linear(0.0, 1.0)).unwrap();
    evaluator.register_constant("pi", Polynomial::constant(PI)).unwrap();
    evaluator.register_constant("e", Polynomial::constant(E)).unwrap();
    evaluator.register_constant("inf", Polynomial::constant(1.0f64 / 0.0f64)).unwrap();
    evaluator.register_constant("nan", Polynomial::constant(0.0f64 / 0.0f64)).unwrap();

    evaluator.register_function("+", Function::new(2, Box::new(functions::addition))).unwrap();
    evaluator.register_function("-", Function::new(2, Box::new(functions::subtraction))).unwrap();
    evaluator.register_function("*", Function::new(2, Box::new(functions::multiplication))).unwrap();
    evaluator.register_function("/", Function::new(2, Box::new(functions::division))).unwrap();
    evaluator.register_function("^", Function::new(2, Box::new(functions::exponentiation))).unwrap();

    evaluator.register_function("log", Function::new(2, Box::new(functions::log))).unwrap();
    evaluator.register_function("log10", Function::new(1, Box::new(functions::log10))).unwrap();
    evaluator.register_function("bind", Function::new(2, Box::new(functions::bind))).unwrap();

    PolynomialEvaluator {
      evaluator: evaluator
    }
  }
}

/// Allows usage of PolynomialEvaluator as common TokensReducer
impl TokensReducer for PolynomialEvaluator {
  fn process(&self, tokens: &Tokens) -> Result<Polynomial, EvaluationError> {
    self.evaluator.process(tokens)
  }
}

/// Extends Parser with common arithmetic operators with correct precedence
/// and associativity.
pub struct PolynomialParser {
  /// Underlying parser (one can use it to extend it furthermore)
  pub parser: Parser
}

/// Creates PolynomialParser and extends basic Parser.
///
/// Common arithmetic operators are registered with the Parser.
impl Default for PolynomialParser {
  fn default() -> PolynomialParser {
    let mut parser = Parser::default();

    parser.register_operator('+', Operator::new(1, OperatorAssociativity::Left));
    parser.register_operator('-', Operator::new(1, OperatorAssociativity::Left));
    parser.register_operator('*', Operator::new(5, OperatorAssociativity::Left));
    parser.register_operator('/', Operator::new(5, OperatorAssociativity::Left));
    parser.register_operator('^', Operator::new(10, OperatorAssociativity::Right));

    PolynomialParser {
      parser: parser
    }
  }
}

/// Allows usage of PolynomialParser as common TokensProcessor
impl TokensProcessor for PolynomialParser {
  fn process(&mut self, tokens: &Tokens) -> Result<&Tokens, ParsingError> {
    self.parser.process(tokens)
  }
}

/// Implementations of function handlers used in operators and functions.
///
/// This module is public, so when you are writing another evaluator, but
/// it does not extend PolynomialEvaluator, you can reuse these functions
/// as handlers for some of the common operations.
///
/// Operations that are directly defined on the Polynomial (such as addition,
/// subtraction, multiplication and division), avoid cloning by using
/// the assignment with operation, thus optimizing memory usage.
pub mod functions {
  use polynomial::Polynomial;
  use EvaluationError;

  /// Adds two polynomials together (requires two arguments).
  pub fn addition(mut args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    let b = args.pop().unwrap();
    let mut a = args.pop().unwrap();

    a += b;
    Ok(a)
  }

  /// Subtracts two polynomials from each other (requires two arguments).
  pub fn subtraction(mut args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    let b = args.pop().unwrap();
    let mut a = args.pop().unwrap();

    a -= b;
    Ok(a)
  }

  /// Multiplies two polynomials together (requires two arguments).
  pub fn multiplication(mut args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    let b = args.pop().unwrap();
    let mut a = args.pop().unwrap();

    a *= b;
    Ok(a)
  }

  /// Divides two polynomials by each other (requires two arguments).
  ///
  /// # Errors
  ///
  /// It will return a wrapped PolynomialError when a degree of divident is
  /// smaller than a degree of divisor or when a divident is non-constant
  /// polynomial, while a divisor is a zero.
  pub fn division(mut args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    let b = args.pop().unwrap();
    let mut a = args.pop().unwrap();

    match (&mut a) / &b {
      Ok(_) => Ok(a),
      Err(e) => Err(EvaluationError::PolynomialError(e))
    }
  }

  /// Computes a logarithm of arbitrary base (requires two constant arguments).
  ///
  /// First arguments is a value to have a logarithm computed on, where a second
  /// argument is a base of the logarithm.
  ///
  /// # Errors
  ///
  /// It will return a wrapped PolynomialError::NonConstantError when any of the
  /// arguments is not a constant polynomial (a polynomial of degree zero).
  pub fn log(args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    Ok(Polynomial::constant(try!(args[0].as_f64()).log(try!(args[1].as_f64()))))
  }

  /// Computes a decimal logarithm (requires a single constant argument).
  ///
  /// # Errors
  ///
  /// It will return a wrapped PolynomialError::NonConstantError when the argument
  /// is not a constant polynomial (a polynomial of degree zero).
  pub fn log10(args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    Ok(Polynomial::constant(try!(args[0].as_f64()).log10()))
  }

  /// Binds a polynomial with a value (requires two arguments).
  ///
  /// This function computes value of given polynomial (first argument) when
  /// the symbol is replaced with a constant value (second argument).
  ///
  /// # Errors
  ///
  /// It will return a wrapped PolynomialError::NonConstantError when the second
  /// argument is not a constant polynomial (a polynomial of degree zero).
  pub fn bind(args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    Ok(args[0].bind(try!(args[1].as_f64())))
  }

  /// Performs exponentiation of polynomial (requires two arguments).
  ///
  /// First argument is an exponentiation base, where second argument is
  /// the exponent (which must be a constant polynomial). Method of exponentiation
  /// is optimized, it depends on degree of the base and a value of the exponent.
  /// Exponentation of complicated polynomials is done subefficiently by multiplication.
  ///
  /// # Errors
  ///
  /// It will return a NonConstantExponent error when the exponient is not
  /// a constant polynomial. Performing such operation would result in a
  /// non-polynomial result.
  ///
  /// It will return a NonNaturalExponent error when the exponient is not
  /// a natural number and the base is not a constant polynomial. Performing
  /// such operation would result in a non-polynomial result.
  pub fn exponentiation(mut args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    let exponent = args.pop().unwrap();
    let base = args.pop().unwrap();

    let base_degree = base.degree();
    let exponent_degree = exponent.degree();

    if exponent_degree > 0 {
      Err(EvaluationError::NonConstantExponent)
    } else
    if exponent[0] == 0.0 {
      Ok(Polynomial::constant(1.0))
    } else
    if base_degree == 0 {
      Ok(Polynomial::constant(base[0].powf(exponent[0])))
    } else
    if exponent[0] > 0.0 && exponent[0].fract() == 0.0 {
      if base_degree == 1 && base[0] == 0.0 {
        let mut v = Polynomial::zero();
        v[exponent[0] as usize] = base[1].powf(exponent[0]);

        Ok(v)
      } else {
        let mut v = base.clone();
        let exp = exponent[0] as usize;

        {
          let mut vr = &mut v;
          for _ in 1..exp {
            vr *= &base;
          }
        }

        Ok(v)
      }
    } else {
      Err(EvaluationError::NonNaturalExponent)
    }
  }
}

#[cfg(test)]
mod tests {
  use polynomial::{Polynomial, PolynomialError};
  use polynomial_calculator::PolynomialCalculator;
  use EvaluationError;
  use calculator::Calculator;
  use calculator::CalculationError;
  use std::f64::consts::{PI, E};

  #[test]
  fn test_general() {
    assert_eq!(PolynomialCalculator.process("(3+(4-1))*5"), Ok(Polynomial::constant(30.0)));
  }

  #[test]
  fn test_constants() {
    assert_eq!(PolynomialCalculator.process("x"), Ok(Polynomial::linear(0.0, 1.0)));
    assert_eq!(PolynomialCalculator.process("pi"), Ok(Polynomial::constant(PI)));
    assert_eq!(PolynomialCalculator.process("e"), Ok(Polynomial::constant(E)));
  }

  #[test]
  fn test_operations() {
    assert_eq!(PolynomialCalculator.process("1+1"), Ok(Polynomial::constant(2.0)));
    assert_eq!(PolynomialCalculator.process("1+-1"), Ok(Polynomial::constant(0.0)));

    assert_eq!(PolynomialCalculator.process("1-1"), Ok(Polynomial::constant(0.0)));
    assert_eq!(PolynomialCalculator.process("1-3"), Ok(Polynomial::constant(-2.0)));
    assert_eq!(PolynomialCalculator.process("1--1"), Ok(Polynomial::constant(2.0)));

    assert_eq!(PolynomialCalculator.process("2*4"), Ok(Polynomial::constant(8.0)));
    assert_eq!(PolynomialCalculator.process("2*0"), Ok(Polynomial::constant(0.0)));

    assert_eq!(PolynomialCalculator.process("2/4"), Ok(Polynomial::constant(0.5)));
    assert!(PolynomialCalculator.process("2/0").unwrap().as_f64().unwrap().is_infinite());
    assert!(PolynomialCalculator.process("0/0").unwrap().as_f64().unwrap().is_nan());

    assert_eq!(PolynomialCalculator.process("2^0"), Ok(Polynomial::constant(1.0)));
    assert_eq!(PolynomialCalculator.process("2^4"), Ok(Polynomial::constant(16.0)));
  }

  #[test]
  fn test_polynomials() {
    assert_eq!(PolynomialCalculator.process("2x+1"), Ok(Polynomial::new(&[1.0, 2.0])));
    assert_eq!(PolynomialCalculator.process("2x+4x"), Ok(Polynomial::new(&[0.0, 6.0])));
    assert_eq!(PolynomialCalculator.process("2x-2x-1"), Ok(Polynomial::new(&[-1.0])));
    assert_eq!(PolynomialCalculator.process("2x--2x"), Ok(Polynomial::new(&[0.0, 4.0])));
    assert_eq!(PolynomialCalculator.process("2x*4x"), Ok(Polynomial::new(&[0.0, 0.0, 8.0])));
    assert_eq!(PolynomialCalculator.process("2x*(4x+1)"), Ok(Polynomial::new(&[0.0, 2.0, 8.0])));
    assert_eq!(PolynomialCalculator.process("2x/x"), Ok(Polynomial::new(&[2.0])));
    assert_eq!(PolynomialCalculator.process("2x/0"), Err(CalculationError::EvaluationError(EvaluationError::PolynomialError(PolynomialError::DivisionByZero))));
    assert_eq!(PolynomialCalculator.process("2x/x^2"), Err(CalculationError::EvaluationError(EvaluationError::PolynomialError(PolynomialError::DividentDegreeMismatch))));
    assert_eq!(PolynomialCalculator.process("(x^2-3x-10)/(x+2)"), Ok(Polynomial::new(&[-5.0, 1.0])));
    assert_eq!(PolynomialCalculator.process("x^5"), Ok(Polynomial::new(&[0.0, 0.0, 0.0, 0.0, 0.0, 1.0])));
    assert_eq!(PolynomialCalculator.process("(x+1)^5"), Ok(Polynomial::new(&[1.0, 5.0, 10.0, 10.0, 5.0, 1.0])));
  }
}
<commit_msg>tested functions<commit_after>//! Defines a PolynomialCalculator with common arithmetic operations, functions
//! and constants already defined.

use super::*;
use calculator::*;
use tokenizer::Tokenizer;
use evaluator::{Evaluator, Function};
use parser::{Parser, Operator, OperatorAssociativity};
use polynomial::Polynomial;
use std::f64::consts::{PI, E};

/// PolynomialCalculator is a calculator using a PolynomialParser and a PolynomialEvaluator
/// to provide multiple default operations.
///
/// This calculator supports addition `+`, subtraction `-`, multiplication `*`,
/// division `/` and exponentiation `^` operators, `log(number, base)`,
/// `log10(number)` and `bind(polynomial, double)` functions, `x`, `inf`, `nan`
/// symbols and `pi` and `e` constants.
///
/// While usage of the calculator is the easiest way of embedding computation
/// engine into your program, please note that a Tokenizer, PolynomialParser and
/// PolynomialEvaluator is created with each call, which requires reallocation
/// of memory.
///
/// # Examples
///
/// ```
/// # use xxcalc::polynomial_calculator::PolynomialCalculator;
/// # use xxcalc::polynomial::Polynomial;
/// # use xxcalc::calculator::Calculator;
/// # use std::f64::consts::PI;
/// assert_eq!(PolynomialCalculator.process("2+2"), Ok(Polynomial::constant(4.0)));
/// assert_eq!(PolynomialCalculator.process("(2+2)*-2"), Ok(Polynomial::constant(-8.0)));
/// assert_eq!(String::from(PolynomialCalculator.process("(x+1)*(-0.13x^18-x^7)").unwrap()), "-0.13x^19-0.13x^18-x^8-x^7");
/// assert_eq!(PolynomialCalculator.process("bind(pi*x^2, 10)"), Ok(Polynomial::constant(PI * 10.0 * 10.0)));
/// ```
pub struct PolynomialCalculator;

impl Calculator<Tokenizer, PolynomialParser, PolynomialEvaluator> for PolynomialCalculator {

}

/// Extends Evaluator with handlers for common operators and functions.
pub struct PolynomialEvaluator {
  /// Underlying evaluator (one can use it to extend it furthermore)
  pub evaluator: Evaluator
}

/// Creates PolynomialEvaluator and extends the basic Evaluator.
///
/// Handlers for common arithmetic operations, functions and some constants
/// are registered to the underlying evaluator.
impl Default for PolynomialEvaluator {
  fn default() -> PolynomialEvaluator {
    let mut evaluator = Evaluator::default();

    evaluator.register_constant("x", Polynomial::linear(0.0, 1.0)).unwrap();
    evaluator.register_constant("pi", Polynomial::constant(PI)).unwrap();
    evaluator.register_constant("e", Polynomial::constant(E)).unwrap();
    evaluator.register_constant("inf", Polynomial::constant(1.0f64 / 0.0f64)).unwrap();
    evaluator.register_constant("nan", Polynomial::constant(0.0f64 / 0.0f64)).unwrap();

    evaluator.register_function("+", Function::new(2, Box::new(functions::addition))).unwrap();
    evaluator.register_function("-", Function::new(2, Box::new(functions::subtraction))).unwrap();
    evaluator.register_function("*", Function::new(2, Box::new(functions::multiplication))).unwrap();
    evaluator.register_function("/", Function::new(2, Box::new(functions::division))).unwrap();
    evaluator.register_function("^", Function::new(2, Box::new(functions::exponentiation))).unwrap();

    evaluator.register_function("log", Function::new(2, Box::new(functions::log))).unwrap();
    evaluator.register_function("log10", Function::new(1, Box::new(functions::log10))).unwrap();
    evaluator.register_function("bind", Function::new(2, Box::new(functions::bind))).unwrap();

    PolynomialEvaluator {
      evaluator: evaluator
    }
  }
}

/// Allows usage of PolynomialEvaluator as common TokensReducer
impl TokensReducer for PolynomialEvaluator {
  fn process(&self, tokens: &Tokens) -> Result<Polynomial, EvaluationError> {
    self.evaluator.process(tokens)
  }
}

/// Extends Parser with common arithmetic operators with correct precedence
/// and associativity.
pub struct PolynomialParser {
  /// Underlying parser (one can use it to extend it furthermore)
  pub parser: Parser
}

/// Creates PolynomialParser and extends basic Parser.
///
/// Common arithmetic operators are registered with the Parser.
impl Default for PolynomialParser {
  fn default() -> PolynomialParser {
    let mut parser = Parser::default();

    parser.register_operator('+', Operator::new(1, OperatorAssociativity::Left));
    parser.register_operator('-', Operator::new(1, OperatorAssociativity::Left));
    parser.register_operator('*', Operator::new(5, OperatorAssociativity::Left));
    parser.register_operator('/', Operator::new(5, OperatorAssociativity::Left));
    parser.register_operator('^', Operator::new(10, OperatorAssociativity::Right));

    PolynomialParser {
      parser: parser
    }
  }
}

/// Allows usage of PolynomialParser as common TokensProcessor
impl TokensProcessor for PolynomialParser {
  fn process(&mut self, tokens: &Tokens) -> Result<&Tokens, ParsingError> {
    self.parser.process(tokens)
  }
}

/// Implementations of function handlers used in operators and functions.
///
/// This module is public, so when you are writing another evaluator, but
/// it does not extend PolynomialEvaluator, you can reuse these functions
/// as handlers for some of the common operations.
///
/// Operations that are directly defined on the Polynomial (such as addition,
/// subtraction, multiplication and division), avoid cloning by using
/// the assignment with operation, thus optimizing memory usage.
pub mod functions {
  use polynomial::Polynomial;
  use EvaluationError;

  /// Adds two polynomials together (requires two arguments).
  pub fn addition(mut args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    let b = args.pop().unwrap();
    let mut a = args.pop().unwrap();

    a += b;
    Ok(a)
  }

  /// Subtracts two polynomials from each other (requires two arguments).
  pub fn subtraction(mut args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    let b = args.pop().unwrap();
    let mut a = args.pop().unwrap();

    a -= b;
    Ok(a)
  }

  /// Multiplies two polynomials together (requires two arguments).
  pub fn multiplication(mut args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    let b = args.pop().unwrap();
    let mut a = args.pop().unwrap();

    a *= b;
    Ok(a)
  }

  /// Divides two polynomials by each other (requires two arguments).
  ///
  /// # Errors
  ///
  /// It will return a wrapped PolynomialError when a degree of divident is
  /// smaller than a degree of divisor or when a divident is non-constant
  /// polynomial, while a divisor is a zero.
  pub fn division(mut args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    let b = args.pop().unwrap();
    let mut a = args.pop().unwrap();

    match (&mut a) / &b {
      Ok(_) => Ok(a),
      Err(e) => Err(EvaluationError::PolynomialError(e))
    }
  }

  /// Computes a logarithm of arbitrary base (requires two constant arguments).
  ///
  /// First arguments is a value to have a logarithm computed on, where a second
  /// argument is a base of the logarithm.
  ///
  /// # Examples
  ///
  /// ```
  /// # use xxcalc::polynomial_calculator::PolynomialCalculator;
  /// # use xxcalc::polynomial::Polynomial;
  /// # use xxcalc::calculator::Calculator;
  /// assert_eq!(PolynomialCalculator.process("log(100, 10)"), Ok(Polynomial::constant(2.0)));
  /// assert_eq!(PolynomialCalculator.process("log(256, 2)"), Ok(Polynomial::constant(8.0)));
  /// ```
  ///
  /// # Errors
  ///
  /// It will return a wrapped PolynomialError::NonConstantError when any of the
  /// arguments is not a constant polynomial (a polynomial of degree zero).
  pub fn log(args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    Ok(Polynomial::constant(try!(args[0].as_f64()).log(try!(args[1].as_f64()))))
  }

  /// Computes a decimal logarithm (requires a single constant argument).
  ///
  /// # Examples
  ///
  /// ```
  /// # use xxcalc::polynomial_calculator::PolynomialCalculator;
  /// # use xxcalc::polynomial::Polynomial;
  /// # use xxcalc::calculator::Calculator;
  /// assert_eq!(PolynomialCalculator.process("log10(100)"), Ok(Polynomial::constant(2.0)));
  /// ```
  ///
  /// # Errors
  ///
  /// It will return a wrapped PolynomialError::NonConstantError when the argument
  /// is not a constant polynomial (a polynomial of degree zero).
  pub fn log10(args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    Ok(Polynomial::constant(try!(args[0].as_f64()).log10()))
  }

  /// Binds a polynomial with a value (requires two arguments).
  ///
  /// This function computes value of given polynomial (first argument) when
  /// the symbol is replaced with a constant value (second argument).
  ///
  /// # Examples
  ///
  /// ```
  /// # use xxcalc::polynomial_calculator::PolynomialCalculator;
  /// # use xxcalc::polynomial::Polynomial;
  /// # use xxcalc::calculator::Calculator;
  /// assert_eq!(PolynomialCalculator.process("bind(x^2, 10)"), Ok(Polynomial::constant(100.0)));
  /// ```
  ///
  /// # Errors
  ///
  /// It will return a wrapped PolynomialError::NonConstantError when the second
  /// argument is not a constant polynomial (a polynomial of degree zero).
  pub fn bind(args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    Ok(args[0].bind(try!(args[1].as_f64())))
  }

  /// Performs exponentiation of polynomial (requires two arguments).
  ///
  /// First argument is an exponentiation base, where second argument is
  /// the exponent (which must be a constant polynomial). Method of exponentiation
  /// is optimized, it depends on degree of the base and a value of the exponent.
  /// Exponentation of complicated polynomials is done subefficiently by multiplication.
  ///
  /// # Errors
  ///
  /// It will return a NonConstantExponent error when the exponient is not
  /// a constant polynomial. Performing such operation would result in a
  /// non-polynomial result.
  ///
  /// It will return a NonNaturalExponent error when the exponient is not
  /// a natural number and the base is not a constant polynomial. Performing
  /// such operation would result in a non-polynomial result.
  pub fn exponentiation(mut args: Vec<Polynomial>) -> Result<Polynomial, EvaluationError> {
    let exponent = args.pop().unwrap();
    let base = args.pop().unwrap();

    let base_degree = base.degree();
    let exponent_degree = exponent.degree();

    if exponent_degree > 0 {
      Err(EvaluationError::NonConstantExponent)
    } else
    if exponent[0] == 0.0 {
      Ok(Polynomial::constant(1.0))
    } else
    if base_degree == 0 {
      Ok(Polynomial::constant(base[0].powf(exponent[0])))
    } else
    if exponent[0] > 0.0 && exponent[0].fract() == 0.0 {
      if base_degree == 1 && base[0] == 0.0 {
        let mut v = Polynomial::zero();
        v[exponent[0] as usize] = base[1].powf(exponent[0]);

        Ok(v)
      } else {
        let mut v = base.clone();
        let exp = exponent[0] as usize;

        {
          let mut vr = &mut v;
          for _ in 1..exp {
            vr *= &base;
          }
        }

        Ok(v)
      }
    } else {
      Err(EvaluationError::NonNaturalExponent)
    }
  }
}

#[cfg(test)]
mod tests {
  use polynomial::{Polynomial, PolynomialError};
  use polynomial_calculator::PolynomialCalculator;
  use EvaluationError;
  use calculator::Calculator;
  use calculator::CalculationError;
  use std::f64::consts::{PI, E};

  #[test]
  fn test_general() {
    assert_eq!(PolynomialCalculator.process("(3+(4-1))*5"), Ok(Polynomial::constant(30.0)));
  }

  #[test]
  fn test_constants() {
    assert_eq!(PolynomialCalculator.process("x"), Ok(Polynomial::linear(0.0, 1.0)));
    assert_eq!(PolynomialCalculator.process("pi"), Ok(Polynomial::constant(PI)));
    assert_eq!(PolynomialCalculator.process("e"), Ok(Polynomial::constant(E)));
  }

  #[test]
  fn test_operations() {
    assert_eq!(PolynomialCalculator.process("1+1"), Ok(Polynomial::constant(2.0)));
    assert_eq!(PolynomialCalculator.process("1+-1"), Ok(Polynomial::constant(0.0)));

    assert_eq!(PolynomialCalculator.process("1-1"), Ok(Polynomial::constant(0.0)));
    assert_eq!(PolynomialCalculator.process("1-3"), Ok(Polynomial::constant(-2.0)));
    assert_eq!(PolynomialCalculator.process("1--1"), Ok(Polynomial::constant(2.0)));

    assert_eq!(PolynomialCalculator.process("2*4"), Ok(Polynomial::constant(8.0)));
    assert_eq!(PolynomialCalculator.process("2*0"), Ok(Polynomial::constant(0.0)));

    assert_eq!(PolynomialCalculator.process("2/4"), Ok(Polynomial::constant(0.5)));
    assert!(PolynomialCalculator.process("2/0").unwrap().as_f64().unwrap().is_infinite());
    assert!(PolynomialCalculator.process("0/0").unwrap().as_f64().unwrap().is_nan());

    assert_eq!(PolynomialCalculator.process("2^0"), Ok(Polynomial::constant(1.0)));
    assert_eq!(PolynomialCalculator.process("2^4"), Ok(Polynomial::constant(16.0)));
  }

  #[test]
  fn test_polynomials() {
    assert_eq!(PolynomialCalculator.process("2x+1"), Ok(Polynomial::new(&[1.0, 2.0])));
    assert_eq!(PolynomialCalculator.process("2x+4x"), Ok(Polynomial::new(&[0.0, 6.0])));
    assert_eq!(PolynomialCalculator.process("2x-2x-1"), Ok(Polynomial::new(&[-1.0])));
    assert_eq!(PolynomialCalculator.process("2x--2x"), Ok(Polynomial::new(&[0.0, 4.0])));
    assert_eq!(PolynomialCalculator.process("2x*4x"), Ok(Polynomial::new(&[0.0, 0.0, 8.0])));
    assert_eq!(PolynomialCalculator.process("2x*(4x+1)"), Ok(Polynomial::new(&[0.0, 2.0, 8.0])));
    assert_eq!(PolynomialCalculator.process("2x/x"), Ok(Polynomial::new(&[2.0])));
    assert_eq!(PolynomialCalculator.process("2x/0"), Err(CalculationError::EvaluationError(EvaluationError::PolynomialError(PolynomialError::DivisionByZero))));
    assert_eq!(PolynomialCalculator.process("2x/x^2"), Err(CalculationError::EvaluationError(EvaluationError::PolynomialError(PolynomialError::DividentDegreeMismatch))));
    assert_eq!(PolynomialCalculator.process("(x^2-3x-10)/(x+2)"), Ok(Polynomial::new(&[-5.0, 1.0])));
    assert_eq!(PolynomialCalculator.process("x^5"), Ok(Polynomial::new(&[0.0, 0.0, 0.0, 0.0, 0.0, 1.0])));
    assert_eq!(PolynomialCalculator.process("(x+1)^5"), Ok(Polynomial::new(&[1.0, 5.0, 10.0, 10.0, 5.0, 1.0])));
  }
}
<|endoftext|>