os: osx
osx_image: xcode8.2
install: &osx_install_sccache >
- travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-apple-darwin &&
+ travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-apple-darwin &&
chmod +x /usr/local/bin/sccache &&
travis_retry curl -o /usr/local/bin/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin &&
chmod +x /usr/local/bin/stamp
- set PATH=C:\Python27;%PATH%
# Download and install sccache
- - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-pc-windows-msvc
- - mv 2017-03-24-sccache-x86_64-pc-windows-msvc sccache.exe
+ - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-pc-windows-msvc
+ - mv 2017-04-04-sccache-x86_64-pc-windows-msvc sccache.exe
- set PATH=%PATH%;%CD%
# Download and install ninja
-Subproject commit 4e95c6b41eca3388f54dd5f7787366ad2df637b5
+Subproject commit 4729175045b41b688ab903120860866ce7a22ba9
if not os.path.exists(rustc_cache):
os.makedirs(rustc_cache)
+ channel = self.stage0_rustc_channel()
+
if self.rustc().startswith(self.bin_root()) and \
(not os.path.exists(self.rustc()) or self.rustc_out_of_date()):
self.print_what_it_means_to_bootstrap()
if os.path.exists(self.bin_root()):
shutil.rmtree(self.bin_root())
- channel = self.stage0_rustc_channel()
filename = "rust-std-{}-{}.tar.gz".format(channel, self.build)
url = "https://static.rust-lang.org/dist/" + self.stage0_rustc_date()
tarball = os.path.join(rustc_cache, filename)
with open(self.rustc_stamp(), 'w') as f:
f.write(self.stage0_rustc_date())
+ if "pc-windows-gnu" in self.build:
+ filename = "rust-mingw-{}-{}.tar.gz".format(channel, self.build)
+ url = "https://static.rust-lang.org/dist/" + self.stage0_rustc_date()
+ tarball = os.path.join(rustc_cache, filename)
+ if not os.path.exists(tarball):
+ get("{}/{}".format(url, filename), tarball, verbose=self.verbose)
+ unpack(tarball, self.bin_root(), match="rust-mingw", verbose=self.verbose)
+
if self.cargo().startswith(self.bin_root()) and \
(not os.path.exists(self.cargo()) or self.cargo_out_of_date()):
self.print_what_it_means_to_bootstrap()
def main():
start_time = time()
+ help_triggered = ('-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1)
try:
bootstrap()
- print("Build completed successfully in %s" % format_build_time(time() - start_time))
+ if not help_triggered:
+ print("Build completed successfully in %s" % format_build_time(time() - start_time))
except (SystemExit, KeyboardInterrupt) as e:
if hasattr(e, 'code') and isinstance(e.code, int):
exit_code = e.code
else:
exit_code = 1
print(e)
- print("Build completed unsuccessfully in %s" % format_build_time(time() - start_time))
+ if not help_triggered:
+ print("Build completed unsuccessfully in %s" % format_build_time(time() - start_time))
sys.exit(exit_code)
if __name__ == '__main__':
}
fn rm_rf(path: &Path) {
- if !path.exists() {
- return
- }
- if path.is_file() {
- return do_op(path, "remove file", |p| fs::remove_file(p));
- }
-
- for file in t!(fs::read_dir(path)) {
- let file = t!(file).path();
+ match path.symlink_metadata() {
+ Err(e) => {
+ if e.kind() == ErrorKind::NotFound {
+ return;
+ }
+ panic!("failed to get metadata for file {}: {}", path.display(), e);
+ },
+ Ok(metadata) => {
+ if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
+ do_op(path, "remove file", |p| fs::remove_file(p));
+ return;
+ }
- if file.is_dir() {
- rm_rf(&file);
- } else {
- // On windows we can't remove a readonly file, and git will
- // often clone files as readonly. As a result, we have some
- // special logic to remove readonly files on windows.
- do_op(&file, "remove file", |p| fs::remove_file(p));
- }
- }
- do_op(path, "remove dir", |p| fs::remove_dir(p));
+ for file in t!(fs::read_dir(path)) {
+ rm_rf(&t!(file).path());
+ }
+ do_op(path, "remove dir", |p| fs::remove_dir(p));
+ },
+ };
}
fn do_op<F>(path: &Path, desc: &str, mut f: F)
{
match f(path) {
Ok(()) => {}
+ // On windows we can't remove a readonly file, and git will often clone files as readonly.
+ // As a result, we have some special logic to remove readonly files on windows.
+ // This is also the reason that we can't use things like fs::remove_dir_all().
Err(ref e) if cfg!(windows) &&
e.kind() == ErrorKind::PermissionDenied => {
- let mut p = t!(path.metadata()).permissions();
+ let mut p = t!(path.symlink_metadata()).permissions();
p.set_readonly(false);
t!(fs::set_permissions(path, p));
f(path).unwrap_or_else(|e| {
use std::path::PathBuf;
use std::process;
-use getopts::{Matches, Options};
+use getopts::Options;
use Build;
use config::Config;
impl Flags {
pub fn parse(args: &[String]) -> Flags {
+ let mut extra_help = String::new();
+ let mut subcommand_help = format!("\
+Usage: x.py <subcommand> [options] [<paths>...]
+
+Subcommands:
+ build Compile either the compiler or libraries
+ test Build and run some test suites
+ bench Build and run some benchmarks
+ doc Build documentation
+ clean Clean out build directories
+ dist Build and/or install distribution artifacts
+
+To learn more about a subcommand, run `./x.py <subcommand> -h`");
+
let mut opts = Options::new();
+ // Options common to all subcommands
opts.optflagmulti("v", "verbose", "use verbose output (-vv for very verbose)");
opts.optflag("i", "incremental", "use incremental compilation");
opts.optopt("", "config", "TOML configuration file for build", "FILE");
opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS");
opts.optflag("h", "help", "print this help message");
- let usage = |n, opts: &Options| -> ! {
- let command = args.get(0).map(|s| &**s);
- let brief = format!("Usage: x.py {} [options] [<args>...]",
- command.unwrap_or("<command>"));
+ // fn usage()
+ let usage = |exit_code: i32, opts: &Options, subcommand_help: &str, extra_help: &str| -> ! {
+ println!("{}", opts.usage(subcommand_help));
+ if !extra_help.is_empty() {
+ println!("{}", extra_help);
+ }
+ process::exit(exit_code);
+ };
+
+ // We can't use getopt to parse the options until we have completed specifying which
+ // options are valid, but under the current implementation, some options are conditional on
+ // the subcommand. Therefore we must manually identify the subcommand first, so that we can
+ // complete the definition of the options. Then we can use the getopt::Matches object from
+ // there on out.
+ let mut possible_subcommands = args.iter().collect::<Vec<_>>();
+ possible_subcommands.retain(|&s|
+ (s == "build")
+ || (s == "test")
+ || (s == "bench")
+ || (s == "doc")
+ || (s == "clean")
+ || (s == "dist"));
+ let subcommand = match possible_subcommands.first() {
+ Some(s) => s,
+ None => {
+ // No subcommand -- show the general usage and subcommand help
+ println!("{}\n", subcommand_help);
+ process::exit(0);
+ }
+ };
- println!("{}", opts.usage(&brief));
- match command {
- Some("build") => {
- println!("\
+ // Some subcommands get extra options
+ match subcommand.as_str() {
+ "test" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
+ "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
+ "dist" => { opts.optflag("", "install", "run installer as well"); },
+ _ => { },
+ };
+
+ // Done specifying what options are possible, so do the getopts parsing
+ let matches = opts.parse(&args[..]).unwrap_or_else(|e| {
+ // Invalid argument/option format
+ println!("\n{}\n", e);
+ usage(1, &opts, &subcommand_help, &extra_help);
+ });
+ // Extra sanity check to make sure we didn't hit this crazy corner case:
+ //
+ // ./x.py --frobulate clean build
+ // ^-- option ^ ^- actual subcommand
+ // \_ arg to option could be mistaken as subcommand
+ let mut pass_sanity_check = true;
+ match matches.free.get(0) {
+ Some(check_subcommand) => {
+ if &check_subcommand != subcommand {
+ pass_sanity_check = false;
+ }
+ },
+ None => {
+ pass_sanity_check = false;
+ }
+ }
+ if !pass_sanity_check {
+ println!("{}\n", subcommand_help);
+ println!("Sorry, I couldn't figure out which subcommand you were trying to specify.\n\
+ You may need to move some options to after the subcommand.\n");
+ process::exit(1);
+ }
+ // Extra help text for some commands
+ match subcommand.as_str() {
+ "build" => {
+ subcommand_help.push_str("\n
Arguments:
- This subcommand accepts a number of positional arguments of directories to
- the crates and/or artifacts to compile. For example:
+ This subcommand accepts a number of paths to directories to the crates
+ and/or artifacts to compile. For example:
./x.py build src/libcore
- ./x.py build src/libproc_macro
+ ./x.py build src/libcore src/libproc_macro
./x.py build src/libstd --stage 1
If no arguments are passed then the complete artifacts for that stage are
For a quick build with a usable compile, you can pass:
- ./x.py build --stage 1 src/libtest
-");
- }
-
- Some("test") => {
- println!("\
+ ./x.py build --stage 1 src/libtest");
+ }
+ "test" => {
+ subcommand_help.push_str("\n
Arguments:
- This subcommand accepts a number of positional arguments of directories to
- tests that should be compiled and run. For example:
+ This subcommand accepts a number of paths to directories to tests that
+ should be compiled and run. For example:
./x.py test src/test/run-pass
./x.py test src/libstd --test-args hash_map
compiled and tested.
./x.py test
- ./x.py test --stage 1
-");
- }
-
- Some("doc") => {
- println!("\
+ ./x.py test --stage 1");
+ }
+ "doc" => {
+ subcommand_help.push_str("\n
Arguments:
- This subcommand accepts a number of positional arguments of directories of
- documentation to build. For example:
+ This subcommand accepts a number of paths to directories of documentation
+ to build. For example:
./x.py doc src/doc/book
./x.py doc src/doc/nomicon
- ./x.py doc src/libstd
+ ./x.py doc src/doc/book src/libstd
If no arguments are passed then everything is documented:
./x.py doc
- ./x.py doc --stage 1
-");
- }
-
- _ => {}
+ ./x.py doc --stage 1");
}
-
- if let Some(command) = command {
- if command == "build" ||
- command == "dist" ||
- command == "doc" ||
- command == "test" ||
- command == "bench" ||
- command == "clean" {
- println!("Available invocations:");
- if args.iter().any(|a| a == "-v") {
- let flags = Flags::parse(&["build".to_string()]);
- let mut config = Config::default();
- config.build = flags.build.clone();
- let mut build = Build::new(flags, config);
- metadata::build(&mut build);
- step::build_rules(&build).print_help(command);
- } else {
- println!(" ... elided, run `./x.py {} -h -v` to see",
- command);
- }
-
- println!("");
- }
- }
-
-println!("\
-Subcommands:
- build Compile either the compiler or libraries
- test Build and run some test suites
- bench Build and run some benchmarks
- doc Build documentation
- clean Clean out build directories
- dist Build and/or install distribution artifacts
-
-To learn more about a subcommand, run `./x.py <command> -h`
-");
-
- process::exit(n);
+ _ => { }
};
- if args.len() == 0 {
- println!("a command must be passed");
- usage(1, &opts);
- }
- let parse = |opts: &Options| {
- let m = opts.parse(&args[1..]).unwrap_or_else(|e| {
- println!("failed to parse options: {}", e);
- usage(1, opts);
- });
- if m.opt_present("h") {
- usage(0, opts);
+ // Get any optional paths which occur after the subcommand
+ let cwd = t!(env::current_dir());
+ let paths = matches.free[1..].iter().map(|p| cwd.join(p)).collect::<Vec<_>>();
+
+
+ // All subcommands can have an optional "Available paths" section
+ if matches.opt_present("verbose") {
+ let flags = Flags::parse(&["build".to_string()]);
+ let mut config = Config::default();
+ config.build = flags.build.clone();
+ let mut build = Build::new(flags, config);
+ metadata::build(&mut build);
+ let maybe_rules_help = step::build_rules(&build).get_help(subcommand);
+ if maybe_rules_help.is_some() {
+ extra_help.push_str(maybe_rules_help.unwrap().as_str());
}
- return m
- };
+ } else {
+ extra_help.push_str(format!("Run `./x.py {} -h -v` to see a list of available paths.",
+ subcommand).as_str());
+ }
- let cwd = t!(env::current_dir());
- let remaining_as_path = |m: &Matches| {
- m.free.iter().map(|p| cwd.join(p)).collect::<Vec<_>>()
- };
+ // User passed in -h/--help?
+ if matches.opt_present("help") {
+ usage(0, &opts, &subcommand_help, &extra_help);
+ }
- let m: Matches;
- let cmd = match &args[0][..] {
+ let cmd = match subcommand.as_str() {
"build" => {
- m = parse(&opts);
- Subcommand::Build { paths: remaining_as_path(&m) }
- }
- "doc" => {
- m = parse(&opts);
- Subcommand::Doc { paths: remaining_as_path(&m) }
+ Subcommand::Build { paths: paths }
}
"test" => {
- opts.optmulti("", "test-args", "extra arguments", "ARGS");
- m = parse(&opts);
Subcommand::Test {
- paths: remaining_as_path(&m),
- test_args: m.opt_strs("test-args"),
+ paths: paths,
+ test_args: matches.opt_strs("test-args"),
}
}
"bench" => {
- opts.optmulti("", "test-args", "extra arguments", "ARGS");
- m = parse(&opts);
Subcommand::Bench {
- paths: remaining_as_path(&m),
- test_args: m.opt_strs("test-args"),
+ paths: paths,
+ test_args: matches.opt_strs("test-args"),
}
}
+ "doc" => {
+ Subcommand::Doc { paths: paths }
+ }
"clean" => {
- m = parse(&opts);
- if m.free.len() > 0 {
- println!("clean takes no arguments");
- usage(1, &opts);
+ if paths.len() > 0 {
+ println!("\nclean takes no arguments\n");
+ usage(1, &opts, &subcommand_help, &extra_help);
}
Subcommand::Clean
}
"dist" => {
- opts.optflag("", "install", "run installer as well");
- m = parse(&opts);
Subcommand::Dist {
- paths: remaining_as_path(&m),
- install: m.opt_present("install"),
+ paths: paths,
+ install: matches.opt_present("install"),
}
}
- "--help" => usage(0, &opts),
- cmd => {
- println!("unknown command: {}", cmd);
- usage(1, &opts);
+ _ => {
+ usage(1, &opts, &subcommand_help, &extra_help);
}
};
- let cfg_file = m.opt_str("config").map(PathBuf::from).or_else(|| {
+ let cfg_file = matches.opt_str("config").map(PathBuf::from).or_else(|| {
if fs::metadata("config.toml").is_ok() {
Some(PathBuf::from("config.toml"))
} else {
}
});
- let mut stage = m.opt_str("stage").map(|j| j.parse().unwrap());
-
- let incremental = m.opt_present("i");
+ let mut stage = matches.opt_str("stage").map(|j| j.parse().unwrap());
- if incremental {
+ if matches.opt_present("incremental") {
if stage.is_none() {
stage = Some(1);
}
}
Flags {
- verbose: m.opt_count("v"),
+ verbose: matches.opt_count("verbose"),
stage: stage,
- on_fail: m.opt_str("on-fail"),
- keep_stage: m.opt_str("keep-stage").map(|j| j.parse().unwrap()),
- build: m.opt_str("build").unwrap_or_else(|| {
+ on_fail: matches.opt_str("on-fail"),
+ keep_stage: matches.opt_str("keep-stage").map(|j| j.parse().unwrap()),
+ build: matches.opt_str("build").unwrap_or_else(|| {
env::var("BUILD").unwrap()
}),
- host: split(m.opt_strs("host")),
- target: split(m.opt_strs("target")),
+ host: split(matches.opt_strs("host")),
+ target: split(matches.opt_strs("target")),
config: cfg_file,
- src: m.opt_str("src").map(PathBuf::from),
- jobs: m.opt_str("jobs").map(|j| j.parse().unwrap()),
+ src: matches.opt_str("src").map(PathBuf::from),
+ jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()),
cmd: cmd,
- incremental: incremental,
+ incremental: matches.opt_present("incremental"),
}
}
}
install_sh(&build, "docs", "rust-docs", stage, host, &prefix,
&docdir, &libdir, &mandir, &empty_dir);
}
+
+ for target in build.config.target.iter() {
+ install_sh(&build, "std", "rust-std", stage, target, &prefix,
+ &docdir, &libdir, &mandir, &empty_dir);
+ }
+
if build.config.rust_save_analysis {
install_sh(&build, "analysis", "rust-analysis", stage, host, &prefix,
&docdir, &libdir, &mandir, &empty_dir);
}
- install_sh(&build, "std", "rust-std", stage, host, &prefix,
- &docdir, &libdir, &mandir, &empty_dir);
+
install_sh(&build, "rustc", "rustc", stage, host, &prefix,
&docdir, &libdir, &mandir, &empty_dir);
t!(fs::remove_dir_all(&empty_dir));
}
}
- pub fn print_help(&self, command: &str) {
+ pub fn get_help(&self, command: &str) -> Option<String> {
let kind = match command {
"build" => Kind::Build,
"doc" => Kind::Doc,
"test" => Kind::Test,
"bench" => Kind::Bench,
"dist" => Kind::Dist,
- _ => return,
+ _ => return None,
};
let rules = self.rules.values().filter(|r| r.kind == kind);
let rules = rules.filter(|r| !r.path.contains("nowhere"));
let mut rules = rules.collect::<Vec<_>>();
rules.sort_by_key(|r| r.path);
- println!("Available paths:\n");
+ let mut help_string = String::from("Available paths:\n");
for rule in rules {
- print!(" ./x.py {} {}", command, rule.path);
-
- println!("");
+ help_string.push_str(format!(" ./x.py {} {}\n", command, rule.path).as_str());
}
+ Some(help_string)
}
/// Construct the top-level build steps that we're going to be executing,
RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/aarch64-unknown-linux-gnueabi/bin
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV TARGETS=arm-linux-androideabi
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabi/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabihf/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/armv7-unknown-linux-gnueabihf/bin
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV RUST_CONFIGURE_ARGS \
export CFLAGS="-fPIC -Wa,-mrelax-relocations=no"
export CXXFLAGS="-Wa,-mrelax-relocations=no"
-MUSL=musl-1.1.14
+MUSL=musl-1.1.16
curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
cd $MUSL
-CFLAGS="$CFLAGS -m32" ./configure --prefix=/musl-i686 --disable-shared --target=i686
-make -j10
+CC=gcc \
+ CFLAGS="$CFLAGS -m32" \
+ ./configure --prefix=/musl-i686 --disable-shared \
+ --target=i686
+make AR=ar RANLIB=ranlib -j10
make install
cd ..
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/rustroot/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV HOSTS=i686-unknown-linux-gnu
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/powerpc-unknown-linux-gnu/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-gnu/bin
RUN ./build-powerpc64le-toolchain.sh
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/rustroot/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV HOSTS=x86_64-unknown-linux-gnu
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV RUST_CONFIGURE_ARGS \
export CFLAGS="-fPIC -Wa,-mrelax-relocations=no"
export CXXFLAGS="-Wa,-mrelax-relocations=no"
-MUSL=musl-1.1.14
+MUSL=musl-1.1.16
curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
cd $MUSL
./configure --prefix=/musl-x86_64 --disable-shared
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/x86_64-unknown-netbsd/bin
lib32stdc++6
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-04-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
- [no_debug](no-debug.md)
- [non_ascii_idents](non-ascii-idents.md)
- [nonzero](nonzero.md)
+- [offset_to](offset-to.md)
- [omit_gdb_pretty_printer_section](omit-gdb-pretty-printer-section.md)
- [on_unimplemented](on-unimplemented.md)
- [once_poison](once-poison.md)
- [slice_concat_ext](slice-concat-ext.md)
- [slice_get_slice](slice-get-slice.md)
- [slice_patterns](slice-patterns.md)
+- [slice_rsplit](slice-rsplit.md)
- [sort_internals](sort-internals.md)
- [sort_unstable](sort-unstable.md)
- [specialization](specialization.md)
- [windows_handle](windows-handle.md)
- [windows_net](windows-net.md)
- [windows_stdio](windows-stdio.md)
-- [windows_subsystem](windows-subsystem.md)
- [zero_one](zero-one.md)
--- /dev/null
+# `offset_to`
+
+The tracking issue for this feature is: [#41079]
+
+[#41079]: https://github.com/rust-lang/rust/issues/41079
+
+------------------------
--- /dev/null
+# `slice_rsplit`
+
+The tracking issue for this feature is: [#41020]
+
+[#41020]: https://github.com/rust-lang/rust/issues/41020
+
+------------------------
+
+The `slice_rsplit` feature enables two methods on slices:
+`slice.rsplit(predicate)` and `slice.rsplit_mut(predicate)`.
+++ /dev/null
-# `windows_subsystem`
-
-The tracking issue for this feature is: [#37499]
-
-[#37499]: https://github.com/rust-lang/rust/issues/37499
-
-------------------------
-
-
-
for c in range(prev_codepoint + 1, NUM_CODEPOINTS):
yield Codepoint(c, None)
+def compress_singletons(singletons):
+ uppers = [] # (upper, # items in lowers)
+ lowers = []
+
+ for i in singletons:
+ upper = i >> 8
+ lower = i & 0xff
+ if len(uppers) == 0 or uppers[-1][0] != upper:
+ uppers.append((upper, 1))
+ else:
+ upper, count = uppers[-1]
+ uppers[-1] = upper, count + 1
+ lowers.append(lower)
+
+ return uppers, lowers
+
+def compress_normal(normal):
+ # lengths 0x00..0x7f are encoded as 00, 01, ..., 7e, 7f
+ # lengths 0x80..0x7fff are encoded as 80 80, 80 81, ..., ff fe, ff ff
+ compressed = [] # [truelen, (truelenaux), falselen, (falselenaux)]
+
+ prev_start = 0
+ for start, count in normal:
+ truelen = start - prev_start
+ falselen = count
+ prev_start = start + count
+
+ assert truelen < 0x8000 and falselen < 0x8000
+ entry = []
+ if truelen > 0x7f:
+ entry.append(0x80 | (truelen >> 8))
+ entry.append(truelen & 0xff)
+ else:
+ entry.append(truelen & 0x7f)
+ if falselen > 0x7f:
+ entry.append(0x80 | (falselen >> 8))
+ entry.append(falselen & 0xff)
+ else:
+ entry.append(falselen & 0x7f)
+
+ compressed.append(entry)
+
+ return compressed
+
+def print_singletons(uppers, lowers, uppersname, lowersname):
+ print("const {}: &'static [(u8, u8)] = &[".format(uppersname))
+ for u, c in uppers:
+ print(" ({:#04x}, {}),".format(u, c))
+ print("];")
+ print("const {}: &'static [u8] = &[".format(lowersname))
+ for i in range(0, len(lowers), 8):
+ print(" {}".format(" ".join("{:#04x},".format(l) for l in lowers[i:i+8])))
+ print("];")
+
+def print_normal(normal, normalname):
+ print("const {}: &'static [u8] = &[".format(normalname))
+ for v in normal:
+ print(" {}".format(" ".join("{:#04x},".format(i) for i in v)))
+ print("];")
+
def main():
file = get_file("http://www.unicode.org/Public/UNIDATA/UnicodeData.txt")
else:
normal0.append((a, b - a))
+ singletons0u, singletons0l = compress_singletons(singletons0)
+ singletons1u, singletons1l = compress_singletons(singletons1)
+ normal0 = compress_normal(normal0)
+ normal1 = compress_normal(normal1)
+
print("""\
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// NOTE: The following code was generated by "src/etc/char_private.py",
// do not edit directly!
-use slice::SliceExt;
-
-fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
- for &s in singletons {
- if x == s {
- return false;
- } else if x < s {
+fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8],
+ normal: &[u8]) -> bool {
+ let xupper = (x >> 8) as u8;
+ let mut lowerstart = 0;
+ for &(upper, lowercount) in singletonuppers {
+ let lowerend = lowerstart + lowercount as usize;
+ if xupper == upper {
+ for &lower in &singletonlowers[lowerstart..lowerend] {
+ if lower == x as u8 {
+ return false;
+ }
+ }
+ } else if xupper < upper {
break;
}
+ lowerstart = lowerend;
}
- for w in normal.chunks(2) {
- let start = w[0];
- let len = w[1];
- let difference = (x as i32) - (start as i32);
- if 0 <= difference {
- if difference < len as i32 {
- return false;
- }
+
+ let mut x = x as i32;
+ let mut normal = normal.iter().cloned();
+ let mut current = true;
+ while let Some(v) = normal.next() {
+ let len = if v & 0x80 != 0 {
+ ((v & 0x7f) as i32) << 8 | normal.next().unwrap() as i32
} else {
+ v as i32
+ };
+ x -= len;
+ if x < 0 {
break;
}
+ current = !current;
}
- true
+ current
}
pub fn is_printable(x: char) -> bool {
let x = x as u32;
let lower = x as u16;
if x < 0x10000 {
- check(lower, SINGLETONS0, NORMAL0)
+ check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0)
} else if x < 0x20000 {
- check(lower, SINGLETONS1, NORMAL1)
+ check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1)
} else {\
""")
for a, b in extra:
}\
""")
print()
- print("const SINGLETONS0: &'static [u16] = &[")
- for s in singletons0:
- print(" 0x{:x},".format(s))
- print("];")
- print("const SINGLETONS1: &'static [u16] = &[")
- for s in singletons1:
- print(" 0x{:x},".format(s))
- print("];")
- print("const NORMAL0: &'static [u16] = &[")
- for a, b in normal0:
- print(" 0x{:x}, 0x{:x},".format(a, b))
- print("];")
- print("const NORMAL1: &'static [u16] = &[")
- for a, b in normal1:
- print(" 0x{:x}, 0x{:x},".format(a, b))
- print("];")
+ print_singletons(singletons0u, singletons0l, 'SINGLETONS0U', 'SINGLETONS0L')
+ print_singletons(singletons1u, singletons1l, 'SINGLETONS1U', 'SINGLETONS1L')
+ print_normal(normal0, 'NORMAL0')
+ print_normal(normal1, 'NORMAL1')
if __name__ == '__main__':
main()
target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe"]
- rustc_dlls = ["libstdc++-6.dll"]
+ rustc_dlls = ["libstdc++-6.dll", "libwinpthread-1.dll"]
if target_triple.startswith("i686-"):
rustc_dlls.append("libgcc_s_dw2-1.dll")
else:
"libstdc++.a",
"libiconv.a",
"libmoldname.a",
+ "libpthread.a",
# Windows import libs
"libadvapi32.a",
"libbcrypt.a",
std_unicode = { path = "../libstd_unicode" }
[[test]]
-name = "collectionstest"
-path = "../libcollectionstest/lib.rs"
+name = "collectionstests"
+path = "../libcollections/tests/lib.rs"
[[bench]]
name = "collectionsbenches"
#![feature(shared)]
#![feature(slice_get_slice)]
#![feature(slice_patterns)]
+#![feature(slice_rsplit)]
#![cfg_attr(not(test), feature(sort_unstable))]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(untagged_unions)]
#![cfg_attr(not(test), feature(str_checked_slicing))]
#![cfg_attr(test, feature(rand, test))]
+#![feature(offset_to)]
#![no_std]
/// Returns a place for insertion at the front of the list.
///
- /// Using this method with placement syntax is equivalent to [`push_front`]
- /// (#method.push_front), but may be more efficient.
+ /// Using this method with placement syntax is equivalent to
+ /// [`push_front`](#method.push_front), but may be more efficient.
///
/// # Examples
///
pub use core::slice::{SplitMut, ChunksMut, Split};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+pub use core::slice::{RSplit, RSplitMut};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
#[unstable(feature = "slice_get_slice", issue = "35729")]
core_slice::SliceExt::split_mut(self, pred)
}
+ /// Returns an iterator over subslices separated by elements that match
+ /// `pred`, starting at the end of the slice and working backwards.
+ /// The matched element is not contained in the subslices.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_rsplit)]
+ ///
+ /// let slice = [11, 22, 33, 0, 44, 55];
+ /// let mut iter = slice.rsplit(|num| *num == 0);
+ ///
+ /// assert_eq!(iter.next().unwrap(), &[44, 55]);
+ /// assert_eq!(iter.next().unwrap(), &[11, 22, 33]);
+ /// assert_eq!(iter.next(), None);
+ /// ```
+ ///
+ /// As with `split()`, if the first or last element is matched, an empty
+ /// slice will be the first (or last) item returned by the iterator.
+ ///
+ /// ```
+ /// #![feature(slice_rsplit)]
+ ///
+ /// let v = &[0, 1, 1, 2, 3, 5, 8];
+ /// let mut it = v.rsplit(|n| *n % 2 == 0);
+ /// assert_eq!(it.next().unwrap(), &[]);
+ /// assert_eq!(it.next().unwrap(), &[3, 5]);
+ /// assert_eq!(it.next().unwrap(), &[1, 1]);
+ /// assert_eq!(it.next().unwrap(), &[]);
+ /// assert_eq!(it.next(), None);
+ /// ```
+ #[unstable(feature = "slice_rsplit", issue = "41020")]
+ #[inline]
+ pub fn rsplit<F>(&self, pred: F) -> RSplit<T, F>
+ where F: FnMut(&T) -> bool
+ {
+ core_slice::SliceExt::rsplit(self, pred)
+ }
+
+ /// Returns an iterator over mutable subslices separated by elements that
+ /// match `pred`, starting at the end of the slice and working
+ /// backwards. The matched element is not contained in the subslices.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_rsplit)]
+ ///
+ /// let mut v = [100, 400, 300, 200, 600, 500];
+ ///
+ /// let mut count = 0;
+ /// for group in v.rsplit_mut(|num| *num % 3 == 0) {
+ /// count += 1;
+ /// group[0] = count;
+ /// }
+ /// assert_eq!(v, [3, 400, 300, 2, 600, 1]);
+ /// ```
+ ///
+ #[unstable(feature = "slice_rsplit", issue = "41020")]
+ #[inline]
+ pub fn rsplit_mut<F>(&mut self, pred: F) -> RSplitMut<T, F>
+ where F: FnMut(&T) -> bool
+ {
+ core_slice::SliceExt::rsplit_mut(self, pred)
+ }
+
/// Returns an iterator over subslices separated by elements that match
/// `pred`, limited to returning at most `n` items. The matched element is
/// not contained in the subslices.
--- /dev/null
+// Copyright 2013-2014 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.
+
+use std::panic;
+use std::collections::BinaryHeap;
+use std::collections::binary_heap::{Drain, PeekMut};
+
+#[test]
+fn test_iterator() {
+ let data = vec![5, 9, 3];
+ let iterout = [9, 5, 3];
+ let heap = BinaryHeap::from(data);
+ let mut i = 0;
+ for el in &heap {
+ assert_eq!(*el, iterout[i]);
+ i += 1;
+ }
+}
+
+#[test]
+fn test_iterator_reverse() {
+ let data = vec![5, 9, 3];
+ let iterout = vec![3, 5, 9];
+ let pq = BinaryHeap::from(data);
+
+ let v: Vec<_> = pq.iter().rev().cloned().collect();
+ assert_eq!(v, iterout);
+}
+
+#[test]
+fn test_move_iter() {
+ let data = vec![5, 9, 3];
+ let iterout = vec![9, 5, 3];
+ let pq = BinaryHeap::from(data);
+
+ let v: Vec<_> = pq.into_iter().collect();
+ assert_eq!(v, iterout);
+}
+
+#[test]
+fn test_move_iter_size_hint() {
+ let data = vec![5, 9];
+ let pq = BinaryHeap::from(data);
+
+ let mut it = pq.into_iter();
+
+ assert_eq!(it.size_hint(), (2, Some(2)));
+ assert_eq!(it.next(), Some(9));
+
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(it.next(), Some(5));
+
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_move_iter_reverse() {
+ let data = vec![5, 9, 3];
+ let iterout = vec![3, 5, 9];
+ let pq = BinaryHeap::from(data);
+
+ let v: Vec<_> = pq.into_iter().rev().collect();
+ assert_eq!(v, iterout);
+}
+
+#[test]
+fn test_peek_and_pop() {
+ let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
+ let mut sorted = data.clone();
+ sorted.sort();
+ let mut heap = BinaryHeap::from(data);
+ while !heap.is_empty() {
+ assert_eq!(heap.peek().unwrap(), sorted.last().unwrap());
+ assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap());
+ }
+}
+
+#[test]
+fn test_peek_mut() {
+ let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
+ let mut heap = BinaryHeap::from(data);
+ assert_eq!(heap.peek(), Some(&10));
+ {
+ let mut top = heap.peek_mut().unwrap();
+ *top -= 2;
+ }
+ assert_eq!(heap.peek(), Some(&9));
+}
+
+#[test]
+fn test_peek_mut_pop() {
+ let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
+ let mut heap = BinaryHeap::from(data);
+ assert_eq!(heap.peek(), Some(&10));
+ {
+ let mut top = heap.peek_mut().unwrap();
+ *top -= 2;
+ assert_eq!(PeekMut::pop(top), 8);
+ }
+ assert_eq!(heap.peek(), Some(&9));
+}
+
+#[test]
+fn test_push() {
+ let mut heap = BinaryHeap::from(vec![2, 4, 9]);
+ assert_eq!(heap.len(), 3);
+ assert!(*heap.peek().unwrap() == 9);
+ heap.push(11);
+ assert_eq!(heap.len(), 4);
+ assert!(*heap.peek().unwrap() == 11);
+ heap.push(5);
+ assert_eq!(heap.len(), 5);
+ assert!(*heap.peek().unwrap() == 11);
+ heap.push(27);
+ assert_eq!(heap.len(), 6);
+ assert!(*heap.peek().unwrap() == 27);
+ heap.push(3);
+ assert_eq!(heap.len(), 7);
+ assert!(*heap.peek().unwrap() == 27);
+ heap.push(103);
+ assert_eq!(heap.len(), 8);
+ assert!(*heap.peek().unwrap() == 103);
+}
+
+#[test]
+fn test_push_unique() {
+ let mut heap = BinaryHeap::<Box<_>>::from(vec![box 2, box 4, box 9]);
+ assert_eq!(heap.len(), 3);
+ assert!(*heap.peek().unwrap() == box 9);
+ heap.push(box 11);
+ assert_eq!(heap.len(), 4);
+ assert!(*heap.peek().unwrap() == box 11);
+ heap.push(box 5);
+ assert_eq!(heap.len(), 5);
+ assert!(*heap.peek().unwrap() == box 11);
+ heap.push(box 27);
+ assert_eq!(heap.len(), 6);
+ assert!(*heap.peek().unwrap() == box 27);
+ heap.push(box 3);
+ assert_eq!(heap.len(), 7);
+ assert!(*heap.peek().unwrap() == box 27);
+ heap.push(box 103);
+ assert_eq!(heap.len(), 8);
+ assert!(*heap.peek().unwrap() == box 103);
+}
+
+#[test]
+#[allow(deprecated)]
+fn test_push_pop() {
+ let mut heap = BinaryHeap::from(vec![5, 5, 2, 1, 3]);
+ assert_eq!(heap.len(), 5);
+ assert_eq!(heap.push_pop(6), 6);
+ assert_eq!(heap.len(), 5);
+ assert_eq!(heap.push_pop(0), 5);
+ assert_eq!(heap.len(), 5);
+ assert_eq!(heap.push_pop(4), 5);
+ assert_eq!(heap.len(), 5);
+ assert_eq!(heap.push_pop(1), 4);
+ assert_eq!(heap.len(), 5);
+}
+
+#[test]
+#[allow(deprecated)]
+fn test_replace() {
+ let mut heap = BinaryHeap::from(vec![5, 5, 2, 1, 3]);
+ assert_eq!(heap.len(), 5);
+ assert_eq!(heap.replace(6).unwrap(), 5);
+ assert_eq!(heap.len(), 5);
+ assert_eq!(heap.replace(0).unwrap(), 6);
+ assert_eq!(heap.len(), 5);
+ assert_eq!(heap.replace(4).unwrap(), 5);
+ assert_eq!(heap.len(), 5);
+ assert_eq!(heap.replace(1).unwrap(), 4);
+ assert_eq!(heap.len(), 5);
+}
+
+fn check_to_vec(mut data: Vec<i32>) {
+ let heap = BinaryHeap::from(data.clone());
+ let mut v = heap.clone().into_vec();
+ v.sort();
+ data.sort();
+
+ assert_eq!(v, data);
+ assert_eq!(heap.into_sorted_vec(), data);
+}
+
+#[test]
+fn test_to_vec() {
+ check_to_vec(vec![]);
+ check_to_vec(vec![5]);
+ check_to_vec(vec![3, 2]);
+ check_to_vec(vec![2, 3]);
+ check_to_vec(vec![5, 1, 2]);
+ check_to_vec(vec![1, 100, 2, 3]);
+ check_to_vec(vec![1, 3, 5, 7, 9, 2, 4, 6, 8, 0]);
+ check_to_vec(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
+ check_to_vec(vec![9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]);
+ check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+ check_to_vec(vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
+ check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]);
+ check_to_vec(vec![5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]);
+}
+
+#[test]
+fn test_empty_pop() {
+ let mut heap = BinaryHeap::<i32>::new();
+ assert!(heap.pop().is_none());
+}
+
+#[test]
+fn test_empty_peek() {
+ let empty = BinaryHeap::<i32>::new();
+ assert!(empty.peek().is_none());
+}
+
+#[test]
+fn test_empty_peek_mut() {
+ let mut empty = BinaryHeap::<i32>::new();
+ assert!(empty.peek_mut().is_none());
+}
+
+#[test]
+#[allow(deprecated)]
+fn test_empty_replace() {
+ let mut heap = BinaryHeap::new();
+ assert!(heap.replace(5).is_none());
+}
+
+#[test]
+fn test_from_iter() {
+ let xs = vec![9, 8, 7, 6, 5, 4, 3, 2, 1];
+
+ let mut q: BinaryHeap<_> = xs.iter().rev().cloned().collect();
+
+ for &x in &xs {
+ assert_eq!(q.pop().unwrap(), x);
+ }
+}
+
+#[test]
+fn test_drain() {
+ let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect();
+
+ assert_eq!(q.drain().take(5).count(), 5);
+
+ assert!(q.is_empty());
+}
+
+#[test]
+fn test_extend_ref() {
+ let mut a = BinaryHeap::new();
+ a.push(1);
+ a.push(2);
+
+ a.extend(&[3, 4, 5]);
+
+ assert_eq!(a.len(), 5);
+ assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]);
+
+ let mut a = BinaryHeap::new();
+ a.push(1);
+ a.push(2);
+ let mut b = BinaryHeap::new();
+ b.push(3);
+ b.push(4);
+ b.push(5);
+
+ a.extend(&b);
+
+ assert_eq!(a.len(), 5);
+ assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]);
+}
+
+#[test]
+fn test_append() {
+ let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]);
+ let mut b = BinaryHeap::from(vec![-20, 5, 43]);
+
+ a.append(&mut b);
+
+ assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
+ assert!(b.is_empty());
+}
+
+#[test]
+fn test_append_to_empty() {
+ let mut a = BinaryHeap::new();
+ let mut b = BinaryHeap::from(vec![-20, 5, 43]);
+
+ a.append(&mut b);
+
+ assert_eq!(a.into_sorted_vec(), [-20, 5, 43]);
+ assert!(b.is_empty());
+}
+
+#[test]
+fn test_extend_specialization() {
+ let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]);
+ let b = BinaryHeap::from(vec![-20, 5, 43]);
+
+ a.extend(b);
+
+ assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
+}
+
+#[test]
+fn test_placement() {
+ let mut a = BinaryHeap::new();
+ &mut a <- 2;
+ &mut a <- 4;
+ &mut a <- 3;
+ assert_eq!(a.peek(), Some(&4));
+ assert_eq!(a.len(), 3);
+ &mut a <- 1;
+ assert_eq!(a.into_sorted_vec(), vec![1, 2, 3, 4]);
+}
+
+#[test]
+fn test_placement_panic() {
+ let mut heap = BinaryHeap::from(vec![1, 2, 3]);
+ fn mkpanic() -> usize { panic!() }
+ let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { &mut heap <- mkpanic(); }));
+ assert_eq!(heap.len(), 3);
+}
+
+#[allow(dead_code)]
+fn assert_covariance() {
+ fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
+ d
+ }
+}
--- /dev/null
+// Copyright 2014 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.
+
+use std::collections::BTreeMap;
+use std::collections::Bound::{self, Excluded, Included, Unbounded};
+use std::collections::btree_map::Entry::{Occupied, Vacant};
+use std::rc::Rc;
+
+use std::iter::FromIterator;
+use super::DeterministicRng;
+
+#[test]
+fn test_basic_large() {
+ let mut map = BTreeMap::new();
+ let size = 10000;
+ assert_eq!(map.len(), 0);
+
+ for i in 0..size {
+ assert_eq!(map.insert(i, 10 * i), None);
+ assert_eq!(map.len(), i + 1);
+ }
+
+ for i in 0..size {
+ assert_eq!(map.get(&i).unwrap(), &(i * 10));
+ }
+
+ for i in size..size * 2 {
+ assert_eq!(map.get(&i), None);
+ }
+
+ for i in 0..size {
+ assert_eq!(map.insert(i, 100 * i), Some(10 * i));
+ assert_eq!(map.len(), size);
+ }
+
+ for i in 0..size {
+ assert_eq!(map.get(&i).unwrap(), &(i * 100));
+ }
+
+ for i in 0..size / 2 {
+ assert_eq!(map.remove(&(i * 2)), Some(i * 200));
+ assert_eq!(map.len(), size - i - 1);
+ }
+
+ for i in 0..size / 2 {
+ assert_eq!(map.get(&(2 * i)), None);
+ assert_eq!(map.get(&(2 * i + 1)).unwrap(), &(i * 200 + 100));
+ }
+
+ for i in 0..size / 2 {
+ assert_eq!(map.remove(&(2 * i)), None);
+ assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
+ assert_eq!(map.len(), size / 2 - i - 1);
+ }
+}
+
+#[test]
+fn test_basic_small() {
+ let mut map = BTreeMap::new();
+ assert_eq!(map.remove(&1), None);
+ assert_eq!(map.get(&1), None);
+ assert_eq!(map.insert(1, 1), None);
+ assert_eq!(map.get(&1), Some(&1));
+ assert_eq!(map.insert(1, 2), Some(1));
+ assert_eq!(map.get(&1), Some(&2));
+ assert_eq!(map.insert(2, 4), None);
+ assert_eq!(map.get(&2), Some(&4));
+ assert_eq!(map.remove(&1), Some(2));
+ assert_eq!(map.remove(&2), Some(4));
+ assert_eq!(map.remove(&1), None);
+}
+
+#[test]
+fn test_iter() {
+ let size = 10000;
+
+ // Forwards
+ let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ fn test<T>(size: usize, mut iter: T)
+ where T: Iterator<Item = (usize, usize)>
+ {
+ for i in 0..size {
+ assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
+ assert_eq!(iter.next().unwrap(), (i, i));
+ }
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+ }
+ test(size, map.iter().map(|(&k, &v)| (k, v)));
+ test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
+ test(size, map.into_iter());
+}
+
+#[test]
+fn test_iter_rev() {
+ let size = 10000;
+
+ // Forwards
+ let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ fn test<T>(size: usize, mut iter: T)
+ where T: Iterator<Item = (usize, usize)>
+ {
+ for i in 0..size {
+ assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
+ assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1));
+ }
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+ }
+ test(size, map.iter().rev().map(|(&k, &v)| (k, v)));
+ test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v)));
+ test(size, map.into_iter().rev());
+}
+
+#[test]
+fn test_values_mut() {
+ let mut a = BTreeMap::new();
+ a.insert(1, String::from("hello"));
+ a.insert(2, String::from("goodbye"));
+
+ for value in a.values_mut() {
+ value.push_str("!");
+ }
+
+ let values: Vec<String> = a.values().cloned().collect();
+ assert_eq!(values, [String::from("hello!"), String::from("goodbye!")]);
+}
+
+#[test]
+fn test_iter_mixed() {
+ let size = 10000;
+
+ // Forwards
+ let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ fn test<T>(size: usize, mut iter: T)
+ where T: Iterator<Item = (usize, usize)> + DoubleEndedIterator
+ {
+ for i in 0..size / 4 {
+ assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2)));
+ assert_eq!(iter.next().unwrap(), (i, i));
+ assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1));
+ }
+ for i in size / 4..size * 3 / 4 {
+ assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i)));
+ assert_eq!(iter.next().unwrap(), (i, i));
+ }
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+ }
+ test(size, map.iter().map(|(&k, &v)| (k, v)));
+ test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
+ test(size, map.into_iter());
+}
+
+#[test]
+fn test_range_small() {
+ let size = 5;
+
+ // Forwards
+ let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ let mut j = 0;
+ for ((&k, &v), i) in map.range(2..).zip(2..size) {
+ assert_eq!(k, i);
+ assert_eq!(v, i);
+ j += 1;
+ }
+ assert_eq!(j, size - 2);
+}
+
+#[test]
+fn test_range_inclusive() {
+ let size = 500;
+
+ let map: BTreeMap<_, _> = (0...size).map(|i| (i, i)).collect();
+
+ fn check<'a, L, R>(lhs: L, rhs: R)
+ where L: IntoIterator<Item=(&'a i32, &'a i32)>,
+ R: IntoIterator<Item=(&'a i32, &'a i32)>,
+ {
+ let lhs: Vec<_> = lhs.into_iter().collect();
+ let rhs: Vec<_> = rhs.into_iter().collect();
+ assert_eq!(lhs, rhs);
+ }
+
+ check(map.range(size + 1...size + 1), vec![]);
+ check(map.range(size...size), vec![(&size, &size)]);
+ check(map.range(size...size + 1), vec![(&size, &size)]);
+ check(map.range(0...0), vec![(&0, &0)]);
+ check(map.range(0...size - 1), map.range(..size));
+ check(map.range(-1...-1), vec![]);
+ check(map.range(-1...size), map.range(..));
+ check(map.range(...size), map.range(..));
+ check(map.range(...200), map.range(..201));
+ check(map.range(5...8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
+ check(map.range(-1...0), vec![(&0, &0)]);
+ check(map.range(-1...2), vec![(&0, &0), (&1, &1), (&2, &2)]);
+}
+
+#[test]
+fn test_range_inclusive_max_value() {
+ let max = ::std::usize::MAX;
+ let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect();
+
+ assert_eq!(map.range(max...max).collect::<Vec<_>>(), &[(&max, &0)]);
+}
+
+#[test]
+fn test_range_equal_empty_cases() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ assert_eq!(map.range((Included(2), Excluded(2))).next(), None);
+ assert_eq!(map.range((Excluded(2), Included(2))).next(), None);
+}
+
+#[test]
+#[should_panic]
+fn test_range_equal_excluded() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ map.range((Excluded(2), Excluded(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_1() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ map.range((Included(3), Included(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_2() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ map.range((Included(3), Excluded(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_3() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ map.range((Excluded(3), Included(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_4() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ map.range((Excluded(3), Excluded(2)));
+}
+
+#[test]
+fn test_range_1000() {
+ let size = 1000;
+ let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ fn test(map: &BTreeMap<u32, u32>, size: u32, min: Bound<&u32>, max: Bound<&u32>) {
+ let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v));
+ let mut pairs = (0..size).map(|i| (i, i));
+
+ for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
+ assert_eq!(kv, pair);
+ }
+ assert_eq!(kvs.next(), None);
+ assert_eq!(pairs.next(), None);
+ }
+ test(&map, size, Included(&0), Excluded(&size));
+ test(&map, size, Unbounded, Excluded(&size));
+ test(&map, size, Included(&0), Included(&(size - 1)));
+ test(&map, size, Unbounded, Included(&(size - 1)));
+ test(&map, size, Included(&0), Unbounded);
+ test(&map, size, Unbounded, Unbounded);
+}
+
+#[test]
+fn test_range_borrowed_key() {
+ let mut map = BTreeMap::new();
+ map.insert("aardvark".to_string(), 1);
+ map.insert("baboon".to_string(), 2);
+ map.insert("coyote".to_string(), 3);
+ map.insert("dingo".to_string(), 4);
+ // NOTE: would like to use simply "b".."d" here...
+ let mut iter = map.range::<str, _>((Included("b"),Excluded("d")));
+ assert_eq!(iter.next(), Some((&"baboon".to_string(), &2)));
+ assert_eq!(iter.next(), Some((&"coyote".to_string(), &3)));
+ assert_eq!(iter.next(), None);
+}
+
+#[test]
+fn test_range() {
+ let size = 200;
+ let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ for i in 0..size {
+ for j in i..size {
+ let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v));
+ let mut pairs = (i..j + 1).map(|i| (i, i));
+
+ for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
+ assert_eq!(kv, pair);
+ }
+ assert_eq!(kvs.next(), None);
+ assert_eq!(pairs.next(), None);
+ }
+ }
+}
+
+#[test]
+fn test_range_mut() {
+ let size = 200;
+ let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ for i in 0..size {
+ for j in i..size {
+ let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v));
+ let mut pairs = (i..j + 1).map(|i| (i, i));
+
+ for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
+ assert_eq!(kv, pair);
+ }
+ assert_eq!(kvs.next(), None);
+ assert_eq!(pairs.next(), None);
+ }
+ }
+}
+
+#[test]
+fn test_borrow() {
+ // make sure these compile -- using the Borrow trait
+ {
+ let mut map = BTreeMap::new();
+ map.insert("0".to_string(), 1);
+ assert_eq!(map["0"], 1);
+ }
+
+ {
+ let mut map = BTreeMap::new();
+ map.insert(Box::new(0), 1);
+ assert_eq!(map[&0], 1);
+ }
+
+ {
+ let mut map = BTreeMap::new();
+ map.insert(Box::new([0, 1]) as Box<[i32]>, 1);
+ assert_eq!(map[&[0, 1][..]], 1);
+ }
+
+ {
+ let mut map = BTreeMap::new();
+ map.insert(Rc::new(0), 1);
+ assert_eq!(map[&0], 1);
+ }
+}
+
+#[test]
+fn test_entry() {
+ let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
+
+ let mut map: BTreeMap<_, _> = xs.iter().cloned().collect();
+
+ // Existing key (insert)
+ match map.entry(1) {
+ Vacant(_) => unreachable!(),
+ Occupied(mut view) => {
+ assert_eq!(view.get(), &10);
+ assert_eq!(view.insert(100), 10);
+ }
+ }
+ assert_eq!(map.get(&1).unwrap(), &100);
+ assert_eq!(map.len(), 6);
+
+
+ // Existing key (update)
+ match map.entry(2) {
+ Vacant(_) => unreachable!(),
+ Occupied(mut view) => {
+ let v = view.get_mut();
+ *v *= 10;
+ }
+ }
+ assert_eq!(map.get(&2).unwrap(), &200);
+ assert_eq!(map.len(), 6);
+
+ // Existing key (take)
+ match map.entry(3) {
+ Vacant(_) => unreachable!(),
+ Occupied(view) => {
+ assert_eq!(view.remove(), 30);
+ }
+ }
+ assert_eq!(map.get(&3), None);
+ assert_eq!(map.len(), 5);
+
+
+ // Inexistent key (insert)
+ match map.entry(10) {
+ Occupied(_) => unreachable!(),
+ Vacant(view) => {
+ assert_eq!(*view.insert(1000), 1000);
+ }
+ }
+ assert_eq!(map.get(&10).unwrap(), &1000);
+ assert_eq!(map.len(), 6);
+}
+
+#[test]
+fn test_extend_ref() {
+ let mut a = BTreeMap::new();
+ a.insert(1, "one");
+ let mut b = BTreeMap::new();
+ b.insert(2, "two");
+ b.insert(3, "three");
+
+ a.extend(&b);
+
+ assert_eq!(a.len(), 3);
+ assert_eq!(a[&1], "one");
+ assert_eq!(a[&2], "two");
+ assert_eq!(a[&3], "three");
+}
+
+#[test]
+fn test_zst() {
+ let mut m = BTreeMap::new();
+ assert_eq!(m.len(), 0);
+
+ assert_eq!(m.insert((), ()), None);
+ assert_eq!(m.len(), 1);
+
+ assert_eq!(m.insert((), ()), Some(()));
+ assert_eq!(m.len(), 1);
+ assert_eq!(m.iter().count(), 1);
+
+ m.clear();
+ assert_eq!(m.len(), 0);
+
+ for _ in 0..100 {
+ m.insert((), ());
+ }
+
+ assert_eq!(m.len(), 1);
+ assert_eq!(m.iter().count(), 1);
+}
+
+// This test's only purpose is to ensure that zero-sized keys with nonsensical orderings
+// do not cause segfaults when used with zero-sized values. All other map behavior is
+// undefined.
+#[test]
+fn test_bad_zst() {
+ use std::cmp::Ordering;
+
+ struct Bad;
+
+ impl PartialEq for Bad {
+ fn eq(&self, _: &Self) -> bool {
+ false
+ }
+ }
+
+ impl Eq for Bad {}
+
+ impl PartialOrd for Bad {
+ fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
+ Some(Ordering::Less)
+ }
+ }
+
+ impl Ord for Bad {
+ fn cmp(&self, _: &Self) -> Ordering {
+ Ordering::Less
+ }
+ }
+
+ let mut m = BTreeMap::new();
+
+ for _ in 0..100 {
+ m.insert(Bad, Bad);
+ }
+}
+
+#[test]
+fn test_clone() {
+ let mut map = BTreeMap::new();
+ let size = 100;
+ assert_eq!(map.len(), 0);
+
+ for i in 0..size {
+ assert_eq!(map.insert(i, 10 * i), None);
+ assert_eq!(map.len(), i + 1);
+ assert_eq!(map, map.clone());
+ }
+
+ for i in 0..size {
+ assert_eq!(map.insert(i, 100 * i), Some(10 * i));
+ assert_eq!(map.len(), size);
+ assert_eq!(map, map.clone());
+ }
+
+ for i in 0..size / 2 {
+ assert_eq!(map.remove(&(i * 2)), Some(i * 200));
+ assert_eq!(map.len(), size - i - 1);
+ assert_eq!(map, map.clone());
+ }
+
+ for i in 0..size / 2 {
+ assert_eq!(map.remove(&(2 * i)), None);
+ assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
+ assert_eq!(map.len(), size / 2 - i - 1);
+ assert_eq!(map, map.clone());
+ }
+}
+
+#[test]
+#[allow(dead_code)]
+fn test_variance() {
+ use std::collections::btree_map::{Iter, IntoIter, Range, Keys, Values};
+
+ fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> {
+ v
+ }
+ fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> {
+ v
+ }
+ fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> {
+ v
+ }
+ fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> {
+ v
+ }
+ fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> {
+ v
+ }
+ fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> {
+ v
+ }
+ fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> {
+ v
+ }
+ fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> {
+ v
+ }
+ fn keys<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> {
+ v
+ }
+ fn vals<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> {
+ v
+ }
+}
+
+#[test]
+fn test_occupied_entry_key() {
+ let mut a = BTreeMap::new();
+ let key = "hello there";
+ let value = "value goes here";
+ assert!(a.is_empty());
+ a.insert(key.clone(), value.clone());
+ assert_eq!(a.len(), 1);
+ assert_eq!(a[key], value);
+
+ match a.entry(key.clone()) {
+ Vacant(_) => panic!(),
+ Occupied(e) => assert_eq!(key, *e.key()),
+ }
+ assert_eq!(a.len(), 1);
+ assert_eq!(a[key], value);
+}
+
+#[test]
+fn test_vacant_entry_key() {
+ let mut a = BTreeMap::new();
+ let key = "hello there";
+ let value = "value goes here";
+
+ assert!(a.is_empty());
+ match a.entry(key.clone()) {
+ Occupied(_) => panic!(),
+ Vacant(e) => {
+ assert_eq!(key, *e.key());
+ e.insert(value.clone());
+ }
+ }
+ assert_eq!(a.len(), 1);
+ assert_eq!(a[key], value);
+}
+
+macro_rules! create_append_test {
+ ($name:ident, $len:expr) => {
+ #[test]
+ fn $name() {
+ let mut a = BTreeMap::new();
+ for i in 0..8 {
+ a.insert(i, i);
+ }
+
+ let mut b = BTreeMap::new();
+ for i in 5..$len {
+ b.insert(i, 2*i);
+ }
+
+ a.append(&mut b);
+
+ assert_eq!(a.len(), $len);
+ assert_eq!(b.len(), 0);
+
+ for i in 0..$len {
+ if i < 5 {
+ assert_eq!(a[&i], i);
+ } else {
+ assert_eq!(a[&i], 2*i);
+ }
+ }
+
+ assert_eq!(a.remove(&($len-1)), Some(2*($len-1)));
+ assert_eq!(a.insert($len-1, 20), None);
+ }
+ };
+}
+
+// These are mostly for testing the algorithm that "fixes" the right edge after insertion.
+// Single node.
+create_append_test!(test_append_9, 9);
+// Two leafs that don't need fixing.
+create_append_test!(test_append_17, 17);
+// Two leafs where the second one ends up underfull and needs stealing at the end.
+create_append_test!(test_append_14, 14);
+// Two leafs where the second one ends up empty because the insertion finished at the root.
+create_append_test!(test_append_12, 12);
+// Three levels; insertion finished at the root.
+create_append_test!(test_append_144, 144);
+// Three levels; insertion finished at leaf while there is an empty node on the second level.
+create_append_test!(test_append_145, 145);
+// Tests for several randomly chosen sizes.
+create_append_test!(test_append_170, 170);
+create_append_test!(test_append_181, 181);
+create_append_test!(test_append_239, 239);
+create_append_test!(test_append_1700, 1700);
+
+fn rand_data(len: usize) -> Vec<(u32, u32)> {
+ let mut rng = DeterministicRng::new();
+ Vec::from_iter((0..len).map(|_| (rng.next(), rng.next())))
+}
+
+#[test]
+fn test_split_off_empty_right() {
+ let mut data = rand_data(173);
+
+ let mut map = BTreeMap::from_iter(data.clone());
+ let right = map.split_off(&(data.iter().max().unwrap().0 + 1));
+
+ data.sort();
+ assert!(map.into_iter().eq(data));
+ assert!(right.into_iter().eq(None));
+}
+
+#[test]
+fn test_split_off_empty_left() {
+ let mut data = rand_data(314);
+
+ let mut map = BTreeMap::from_iter(data.clone());
+ let right = map.split_off(&data.iter().min().unwrap().0);
+
+ data.sort();
+ assert!(map.into_iter().eq(None));
+ assert!(right.into_iter().eq(data));
+}
+
+#[test]
+fn test_split_off_large_random_sorted() {
+ let mut data = rand_data(1529);
+ // special case with maximum height.
+ data.sort();
+
+ let mut map = BTreeMap::from_iter(data.clone());
+ let key = data[data.len() / 2].0;
+ let right = map.split_off(&key);
+
+ assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key)));
+ assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key)));
+}
--- /dev/null
+// Copyright 2014 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.
+
+mod map;
+mod set;
+
+/// XorShiftRng
+struct DeterministicRng {
+ x: u32,
+ y: u32,
+ z: u32,
+ w: u32,
+}
+
+impl DeterministicRng {
+ fn new() -> Self {
+ DeterministicRng {
+ x: 0x193a6754,
+ y: 0xa8a7d469,
+ z: 0x97830e05,
+ w: 0x113ba7bb,
+ }
+ }
+
+ fn next(&mut self) -> u32 {
+ let x = self.x;
+ let t = x ^ (x << 11);
+ self.x = self.y;
+ self.y = self.z;
+ self.z = self.w;
+ let w_ = self.w;
+ self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
+ self.w
+ }
+}
--- /dev/null
+// Copyright 2014 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.
+
+use std::collections::BTreeSet;
+
+use std::iter::FromIterator;
+use super::DeterministicRng;
+
+#[test]
+fn test_clone_eq() {
+ let mut m = BTreeSet::new();
+
+ m.insert(1);
+ m.insert(2);
+
+ assert!(m.clone() == m);
+}
+
+#[test]
+fn test_hash() {
+ let mut x = BTreeSet::new();
+ let mut y = BTreeSet::new();
+
+ x.insert(1);
+ x.insert(2);
+ x.insert(3);
+
+ y.insert(3);
+ y.insert(2);
+ y.insert(1);
+
+ assert!(::hash(&x) == ::hash(&y));
+}
+
+fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F)
+ where F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut FnMut(&i32) -> bool) -> bool
+{
+ let mut set_a = BTreeSet::new();
+ let mut set_b = BTreeSet::new();
+
+ for x in a {
+ assert!(set_a.insert(*x))
+ }
+ for y in b {
+ assert!(set_b.insert(*y))
+ }
+
+ let mut i = 0;
+ f(&set_a,
+ &set_b,
+ &mut |&x| {
+ assert_eq!(x, expected[i]);
+ i += 1;
+ true
+ });
+ assert_eq!(i, expected.len());
+}
+
+#[test]
+fn test_intersection() {
+ fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) {
+ check(a, b, expected, |x, y, f| x.intersection(y).all(f))
+ }
+
+ check_intersection(&[], &[], &[]);
+ check_intersection(&[1, 2, 3], &[], &[]);
+ check_intersection(&[], &[1, 2, 3], &[]);
+ check_intersection(&[2], &[1, 2, 3], &[2]);
+ check_intersection(&[1, 2, 3], &[2], &[2]);
+ check_intersection(&[11, 1, 3, 77, 103, 5, -5],
+ &[2, 11, 77, -9, -42, 5, 3],
+ &[3, 5, 11, 77]);
+}
+
+#[test]
+fn test_difference() {
+ fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) {
+ check(a, b, expected, |x, y, f| x.difference(y).all(f))
+ }
+
+ check_difference(&[], &[], &[]);
+ check_difference(&[1, 12], &[], &[1, 12]);
+ check_difference(&[], &[1, 2, 3, 9], &[]);
+ check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]);
+ check_difference(&[-5, 11, 22, 33, 40, 42],
+ &[-12, -5, 14, 23, 34, 38, 39, 50],
+ &[11, 22, 33, 40, 42]);
+}
+
+#[test]
+fn test_symmetric_difference() {
+ fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) {
+ check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f))
+ }
+
+ check_symmetric_difference(&[], &[], &[]);
+ check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]);
+ check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]);
+ check_symmetric_difference(&[1, 3, 5, 9, 11],
+ &[-2, 3, 9, 14, 22],
+ &[-2, 1, 5, 11, 14, 22]);
+}
+
+#[test]
+fn test_union() {
+ fn check_union(a: &[i32], b: &[i32], expected: &[i32]) {
+ check(a, b, expected, |x, y, f| x.union(y).all(f))
+ }
+
+ check_union(&[], &[], &[]);
+ check_union(&[1, 2, 3], &[2], &[1, 2, 3]);
+ check_union(&[2], &[1, 2, 3], &[1, 2, 3]);
+ check_union(&[1, 3, 5, 9, 11, 16, 19, 24],
+ &[-2, 1, 5, 9, 13, 19],
+ &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]);
+}
+
+#[test]
+fn test_zip() {
+ let mut x = BTreeSet::new();
+ x.insert(5);
+ x.insert(12);
+ x.insert(11);
+
+ let mut y = BTreeSet::new();
+ y.insert("foo");
+ y.insert("bar");
+
+ let x = x;
+ let y = y;
+ let mut z = x.iter().zip(&y);
+
+ assert_eq!(z.next().unwrap(), (&5, &("bar")));
+ assert_eq!(z.next().unwrap(), (&11, &("foo")));
+ assert!(z.next().is_none());
+}
+
+#[test]
+fn test_from_iter() {
+ let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+
+ let set: BTreeSet<_> = xs.iter().cloned().collect();
+
+ for x in &xs {
+ assert!(set.contains(x));
+ }
+}
+
+#[test]
+fn test_show() {
+ let mut set = BTreeSet::new();
+ let empty = BTreeSet::<i32>::new();
+
+ set.insert(1);
+ set.insert(2);
+
+ let set_str = format!("{:?}", set);
+
+ assert_eq!(set_str, "{1, 2}");
+ assert_eq!(format!("{:?}", empty), "{}");
+}
+
+#[test]
+fn test_extend_ref() {
+ let mut a = BTreeSet::new();
+ a.insert(1);
+
+ a.extend(&[2, 3, 4]);
+
+ assert_eq!(a.len(), 4);
+ assert!(a.contains(&1));
+ assert!(a.contains(&2));
+ assert!(a.contains(&3));
+ assert!(a.contains(&4));
+
+ let mut b = BTreeSet::new();
+ b.insert(5);
+ b.insert(6);
+
+ a.extend(&b);
+
+ assert_eq!(a.len(), 6);
+ assert!(a.contains(&1));
+ assert!(a.contains(&2));
+ assert!(a.contains(&3));
+ assert!(a.contains(&4));
+ assert!(a.contains(&5));
+ assert!(a.contains(&6));
+}
+
+#[test]
+fn test_recovery() {
+ use std::cmp::Ordering;
+
+ #[derive(Debug)]
+ struct Foo(&'static str, i32);
+
+ impl PartialEq for Foo {
+ fn eq(&self, other: &Self) -> bool {
+ self.0 == other.0
+ }
+ }
+
+ impl Eq for Foo {}
+
+ impl PartialOrd for Foo {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.0.partial_cmp(&other.0)
+ }
+ }
+
+ impl Ord for Foo {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.0.cmp(&other.0)
+ }
+ }
+
+ let mut s = BTreeSet::new();
+ assert_eq!(s.replace(Foo("a", 1)), None);
+ assert_eq!(s.len(), 1);
+ assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1)));
+ assert_eq!(s.len(), 1);
+
+ {
+ let mut it = s.iter();
+ assert_eq!(it.next(), Some(&Foo("a", 2)));
+ assert_eq!(it.next(), None);
+ }
+
+ assert_eq!(s.get(&Foo("a", 1)), Some(&Foo("a", 2)));
+ assert_eq!(s.take(&Foo("a", 1)), Some(Foo("a", 2)));
+ assert_eq!(s.len(), 0);
+
+ assert_eq!(s.get(&Foo("a", 1)), None);
+ assert_eq!(s.take(&Foo("a", 1)), None);
+
+ assert_eq!(s.iter().next(), None);
+}
+
+#[test]
+#[allow(dead_code)]
+fn test_variance() {
+ use std::collections::btree_set::{IntoIter, Iter, Range};
+
+ fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> {
+ v
+ }
+ fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
+ v
+ }
+ fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> {
+ v
+ }
+ fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> {
+ v
+ }
+}
+
+#[test]
+fn test_append() {
+ let mut a = BTreeSet::new();
+ a.insert(1);
+ a.insert(2);
+ a.insert(3);
+
+ let mut b = BTreeSet::new();
+ b.insert(3);
+ b.insert(4);
+ b.insert(5);
+
+ a.append(&mut b);
+
+ assert_eq!(a.len(), 5);
+ assert_eq!(b.len(), 0);
+
+ assert_eq!(a.contains(&1), true);
+ assert_eq!(a.contains(&2), true);
+ assert_eq!(a.contains(&3), true);
+ assert_eq!(a.contains(&4), true);
+ assert_eq!(a.contains(&5), true);
+}
+
+fn rand_data(len: usize) -> Vec<u32> {
+ let mut rng = DeterministicRng::new();
+ Vec::from_iter((0..len).map(|_| rng.next()))
+}
+
+#[test]
+fn test_split_off_empty_right() {
+ let mut data = rand_data(173);
+
+ let mut set = BTreeSet::from_iter(data.clone());
+ let right = set.split_off(&(data.iter().max().unwrap() + 1));
+
+ data.sort();
+ assert!(set.into_iter().eq(data));
+ assert!(right.into_iter().eq(None));
+}
+
+#[test]
+fn test_split_off_empty_left() {
+ let mut data = rand_data(314);
+
+ let mut set = BTreeSet::from_iter(data.clone());
+ let right = set.split_off(data.iter().min().unwrap());
+
+ data.sort();
+ assert!(set.into_iter().eq(None));
+ assert!(right.into_iter().eq(data));
+}
+
+#[test]
+fn test_split_off_large_random_sorted() {
+ let mut data = rand_data(1529);
+ // special case with maximum height.
+ data.sort();
+
+ let mut set = BTreeSet::from_iter(data.clone());
+ let key = data[data.len() / 2];
+ let right = set.split_off(&key);
+
+ assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key)));
+ assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key)));
+}
--- /dev/null
+// Copyright 2016 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.
+
+use std::borrow::Cow;
+
+// check that Cow<'a, str> implements addition
+#[test]
+fn check_cow_add_cow() {
+ let borrowed1 = Cow::Borrowed("Hello, ");
+ let borrowed2 = Cow::Borrowed("World!");
+ let borrow_empty = Cow::Borrowed("");
+
+ let owned1: Cow<str> = Cow::Owned(String::from("Hi, "));
+ let owned2: Cow<str> = Cow::Owned(String::from("Rustaceans!"));
+ let owned_empty: Cow<str> = Cow::Owned(String::new());
+
+ assert_eq!("Hello, World!", borrowed1.clone() + borrowed2.clone());
+ assert_eq!("Hello, Rustaceans!", borrowed1.clone() + owned2.clone());
+
+ assert_eq!("Hi, World!", owned1.clone() + borrowed2.clone());
+ assert_eq!("Hi, Rustaceans!", owned1.clone() + owned2.clone());
+
+ if let Cow::Owned(_) = borrowed1.clone() + borrow_empty.clone() {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+ if let Cow::Owned(_) = borrow_empty.clone() + borrowed1.clone() {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+ if let Cow::Owned(_) = borrowed1.clone() + owned_empty.clone() {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+ if let Cow::Owned(_) = owned_empty.clone() + borrowed1.clone() {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+}
+
+#[test]
+fn check_cow_add_str() {
+ let borrowed = Cow::Borrowed("Hello, ");
+ let borrow_empty = Cow::Borrowed("");
+
+ let owned: Cow<str> = Cow::Owned(String::from("Hi, "));
+ let owned_empty: Cow<str> = Cow::Owned(String::new());
+
+ assert_eq!("Hello, World!", borrowed.clone() + "World!");
+
+ assert_eq!("Hi, World!", owned.clone() + "World!");
+
+ if let Cow::Owned(_) = borrowed.clone() + "" {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+ if let Cow::Owned(_) = borrow_empty.clone() + "Hello, " {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+ if let Cow::Owned(_) = owned_empty.clone() + "Hello, " {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+}
+
+#[test]
+fn check_cow_add_assign_cow() {
+ let mut borrowed1 = Cow::Borrowed("Hello, ");
+ let borrowed2 = Cow::Borrowed("World!");
+ let borrow_empty = Cow::Borrowed("");
+
+ let mut owned1: Cow<str> = Cow::Owned(String::from("Hi, "));
+ let owned2: Cow<str> = Cow::Owned(String::from("Rustaceans!"));
+ let owned_empty: Cow<str> = Cow::Owned(String::new());
+
+ let mut s = borrowed1.clone();
+ s += borrow_empty.clone();
+ assert_eq!("Hello, ", s);
+ if let Cow::Owned(_) = s {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+ let mut s = borrow_empty.clone();
+ s += borrowed1.clone();
+ assert_eq!("Hello, ", s);
+ if let Cow::Owned(_) = s {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+ let mut s = borrowed1.clone();
+ s += owned_empty.clone();
+ assert_eq!("Hello, ", s);
+ if let Cow::Owned(_) = s {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+ let mut s = owned_empty.clone();
+ s += borrowed1.clone();
+ assert_eq!("Hello, ", s);
+ if let Cow::Owned(_) = s {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+
+ owned1 += borrowed2;
+ borrowed1 += owned2;
+
+ assert_eq!("Hi, World!", owned1);
+ assert_eq!("Hello, Rustaceans!", borrowed1);
+}
+
+#[test]
+fn check_cow_add_assign_str() {
+ let mut borrowed = Cow::Borrowed("Hello, ");
+ let borrow_empty = Cow::Borrowed("");
+
+ let mut owned: Cow<str> = Cow::Owned(String::from("Hi, "));
+ let owned_empty: Cow<str> = Cow::Owned(String::new());
+
+ let mut s = borrowed.clone();
+ s += "";
+ assert_eq!("Hello, ", s);
+ if let Cow::Owned(_) = s {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+ let mut s = borrow_empty.clone();
+ s += "World!";
+ assert_eq!("World!", s);
+ if let Cow::Owned(_) = s {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+ let mut s = owned_empty.clone();
+ s += "World!";
+ assert_eq!("World!", s);
+ if let Cow::Owned(_) = s {
+ panic!("Adding empty strings to a borrow should note allocate");
+ }
+
+ owned += "World!";
+ borrowed += "World!";
+
+ assert_eq!("Hi, World!", owned);
+ assert_eq!("Hello, World!", borrowed);
+}
--- /dev/null
+// Copyright 2013-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.
+
+use std::fmt;
+
+#[test]
+fn test_format() {
+ let s = fmt::format(format_args!("Hello, {}!", "world"));
+ assert_eq!(s, "Hello, world!");
+}
--- /dev/null
+// Copyright 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.
+
+#![deny(warnings)]
+
+#![feature(binary_heap_extras)]
+#![feature(binary_heap_peek_mut_pop)]
+#![feature(box_syntax)]
+#![feature(inclusive_range_syntax)]
+#![feature(collection_placement)]
+#![feature(collections)]
+#![feature(const_fn)]
+#![feature(exact_size_is_empty)]
+#![feature(pattern)]
+#![feature(placement_in_syntax)]
+#![feature(rand)]
+#![feature(step_by)]
+#![feature(str_escape)]
+#![feature(test)]
+#![feature(unboxed_closures)]
+#![feature(unicode)]
+#![feature(utf8_error_error_len)]
+
+extern crate collections;
+extern crate test;
+extern crate std_unicode;
+extern crate core;
+
+use std::hash::{Hash, Hasher};
+use std::collections::hash_map::DefaultHasher;
+
+mod binary_heap;
+mod btree;
+mod cow_str;
+mod fmt;
+mod linked_list;
+mod slice;
+mod str;
+mod string;
+mod vec_deque;
+mod vec;
+
+fn hash<T: Hash>(t: &T) -> u64 {
+ let mut s = DefaultHasher::new();
+ t.hash(&mut s);
+ s.finish()
+}
--- /dev/null
+// 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.
+
+use std::collections::LinkedList;
+
+#[test]
+fn test_basic() {
+ let mut m = LinkedList::<Box<_>>::new();
+ assert_eq!(m.pop_front(), None);
+ assert_eq!(m.pop_back(), None);
+ assert_eq!(m.pop_front(), None);
+ m.push_front(box 1);
+ assert_eq!(m.pop_front(), Some(box 1));
+ m.push_back(box 2);
+ m.push_back(box 3);
+ assert_eq!(m.len(), 2);
+ assert_eq!(m.pop_front(), Some(box 2));
+ assert_eq!(m.pop_front(), Some(box 3));
+ assert_eq!(m.len(), 0);
+ assert_eq!(m.pop_front(), None);
+ m.push_back(box 1);
+ m.push_back(box 3);
+ m.push_back(box 5);
+ m.push_back(box 7);
+ assert_eq!(m.pop_front(), Some(box 1));
+
+ let mut n = LinkedList::new();
+ n.push_front(2);
+ n.push_front(3);
+ {
+ assert_eq!(n.front().unwrap(), &3);
+ let x = n.front_mut().unwrap();
+ assert_eq!(*x, 3);
+ *x = 0;
+ }
+ {
+ assert_eq!(n.back().unwrap(), &2);
+ let y = n.back_mut().unwrap();
+ assert_eq!(*y, 2);
+ *y = 1;
+ }
+ assert_eq!(n.pop_front(), Some(0));
+ assert_eq!(n.pop_front(), Some(1));
+}
+
+#[cfg(test)]
+fn generate_test() -> LinkedList<i32> {
+ list_from(&[0, 1, 2, 3, 4, 5, 6])
+}
+
+#[cfg(test)]
+fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> {
+ v.iter().cloned().collect()
+}
+
+#[test]
+fn test_split_off() {
+ // singleton
+ {
+ let mut m = LinkedList::new();
+ m.push_back(1);
+
+ let p = m.split_off(0);
+ assert_eq!(m.len(), 0);
+ assert_eq!(p.len(), 1);
+ assert_eq!(p.back(), Some(&1));
+ assert_eq!(p.front(), Some(&1));
+ }
+
+ // not singleton, forwards
+ {
+ let u = vec![1, 2, 3, 4, 5];
+ let mut m = list_from(&u);
+ let mut n = m.split_off(2);
+ assert_eq!(m.len(), 2);
+ assert_eq!(n.len(), 3);
+ for elt in 1..3 {
+ assert_eq!(m.pop_front(), Some(elt));
+ }
+ for elt in 3..6 {
+ assert_eq!(n.pop_front(), Some(elt));
+ }
+ }
+ // not singleton, backwards
+ {
+ let u = vec![1, 2, 3, 4, 5];
+ let mut m = list_from(&u);
+ let mut n = m.split_off(4);
+ assert_eq!(m.len(), 4);
+ assert_eq!(n.len(), 1);
+ for elt in 1..5 {
+ assert_eq!(m.pop_front(), Some(elt));
+ }
+ for elt in 5..6 {
+ assert_eq!(n.pop_front(), Some(elt));
+ }
+ }
+
+ // no-op on the last index
+ {
+ let mut m = LinkedList::new();
+ m.push_back(1);
+
+ let p = m.split_off(1);
+ assert_eq!(m.len(), 1);
+ assert_eq!(p.len(), 0);
+ assert_eq!(m.back(), Some(&1));
+ assert_eq!(m.front(), Some(&1));
+ }
+
+}
+
+#[test]
+fn test_iterator() {
+ let m = generate_test();
+ for (i, elt) in m.iter().enumerate() {
+ assert_eq!(i as i32, *elt);
+ }
+ let mut n = LinkedList::new();
+ assert_eq!(n.iter().next(), None);
+ n.push_front(4);
+ let mut it = n.iter();
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(it.next().unwrap(), &4);
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_iterator_clone() {
+ let mut n = LinkedList::new();
+ n.push_back(2);
+ n.push_back(3);
+ n.push_back(4);
+ let mut it = n.iter();
+ it.next();
+ let mut jt = it.clone();
+ assert_eq!(it.next(), jt.next());
+ assert_eq!(it.next_back(), jt.next_back());
+ assert_eq!(it.next(), jt.next());
+}
+
+#[test]
+fn test_iterator_double_end() {
+ let mut n = LinkedList::new();
+ assert_eq!(n.iter().next(), None);
+ n.push_front(4);
+ n.push_front(5);
+ n.push_front(6);
+ let mut it = n.iter();
+ assert_eq!(it.size_hint(), (3, Some(3)));
+ assert_eq!(it.next().unwrap(), &6);
+ assert_eq!(it.size_hint(), (2, Some(2)));
+ assert_eq!(it.next_back().unwrap(), &4);
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(it.next_back().unwrap(), &5);
+ assert_eq!(it.next_back(), None);
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_rev_iter() {
+ let m = generate_test();
+ for (i, elt) in m.iter().rev().enumerate() {
+ assert_eq!((6 - i) as i32, *elt);
+ }
+ let mut n = LinkedList::new();
+ assert_eq!(n.iter().rev().next(), None);
+ n.push_front(4);
+ let mut it = n.iter().rev();
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(it.next().unwrap(), &4);
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_mut_iter() {
+ let mut m = generate_test();
+ let mut len = m.len();
+ for (i, elt) in m.iter_mut().enumerate() {
+ assert_eq!(i as i32, *elt);
+ len -= 1;
+ }
+ assert_eq!(len, 0);
+ let mut n = LinkedList::new();
+ assert!(n.iter_mut().next().is_none());
+ n.push_front(4);
+ n.push_back(5);
+ let mut it = n.iter_mut();
+ assert_eq!(it.size_hint(), (2, Some(2)));
+ assert!(it.next().is_some());
+ assert!(it.next().is_some());
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert!(it.next().is_none());
+}
+
+#[test]
+fn test_iterator_mut_double_end() {
+ let mut n = LinkedList::new();
+ assert!(n.iter_mut().next_back().is_none());
+ n.push_front(4);
+ n.push_front(5);
+ n.push_front(6);
+ let mut it = n.iter_mut();
+ assert_eq!(it.size_hint(), (3, Some(3)));
+ assert_eq!(*it.next().unwrap(), 6);
+ assert_eq!(it.size_hint(), (2, Some(2)));
+ assert_eq!(*it.next_back().unwrap(), 4);
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(*it.next_back().unwrap(), 5);
+ assert!(it.next_back().is_none());
+ assert!(it.next().is_none());
+}
+
+#[test]
+fn test_mut_rev_iter() {
+ let mut m = generate_test();
+ for (i, elt) in m.iter_mut().rev().enumerate() {
+ assert_eq!((6 - i) as i32, *elt);
+ }
+ let mut n = LinkedList::new();
+ assert!(n.iter_mut().rev().next().is_none());
+ n.push_front(4);
+ let mut it = n.iter_mut().rev();
+ assert!(it.next().is_some());
+ assert!(it.next().is_none());
+}
+
+#[test]
+fn test_eq() {
+ let mut n = list_from(&[]);
+ let mut m = list_from(&[]);
+ assert!(n == m);
+ n.push_front(1);
+ assert!(n != m);
+ m.push_back(1);
+ assert!(n == m);
+
+ let n = list_from(&[2, 3, 4]);
+ let m = list_from(&[1, 2, 3]);
+ assert!(n != m);
+}
+
+#[test]
+fn test_hash() {
+ let mut x = LinkedList::new();
+ let mut y = LinkedList::new();
+
+ assert!(::hash(&x) == ::hash(&y));
+
+ x.push_back(1);
+ x.push_back(2);
+ x.push_back(3);
+
+ y.push_front(3);
+ y.push_front(2);
+ y.push_front(1);
+
+ assert!(::hash(&x) == ::hash(&y));
+}
+
+#[test]
+fn test_ord() {
+ let n = list_from(&[]);
+ let m = list_from(&[1, 2, 3]);
+ assert!(n < m);
+ assert!(m > n);
+ assert!(n <= n);
+ assert!(n >= n);
+}
+
+#[test]
+fn test_ord_nan() {
+ let nan = 0.0f64 / 0.0;
+ let n = list_from(&[nan]);
+ let m = list_from(&[nan]);
+ assert!(!(n < m));
+ assert!(!(n > m));
+ assert!(!(n <= m));
+ assert!(!(n >= m));
+
+ let n = list_from(&[nan]);
+ let one = list_from(&[1.0f64]);
+ assert!(!(n < one));
+ assert!(!(n > one));
+ assert!(!(n <= one));
+ assert!(!(n >= one));
+
+ let u = list_from(&[1.0f64, 2.0, nan]);
+ let v = list_from(&[1.0f64, 2.0, 3.0]);
+ assert!(!(u < v));
+ assert!(!(u > v));
+ assert!(!(u <= v));
+ assert!(!(u >= v));
+
+ let s = list_from(&[1.0f64, 2.0, 4.0, 2.0]);
+ let t = list_from(&[1.0f64, 2.0, 3.0, 2.0]);
+ assert!(!(s < t));
+ assert!(s > one);
+ assert!(!(s <= one));
+ assert!(s >= one);
+}
+
+#[test]
+fn test_show() {
+ let list: LinkedList<_> = (0..10).collect();
+ assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+
+ let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect();
+ assert_eq!(format!("{:?}", list),
+ "[\"just\", \"one\", \"test\", \"more\"]");
+}
+
+#[test]
+fn test_extend_ref() {
+ let mut a = LinkedList::new();
+ a.push_back(1);
+
+ a.extend(&[2, 3, 4]);
+
+ assert_eq!(a.len(), 4);
+ assert_eq!(a, list_from(&[1, 2, 3, 4]));
+
+ let mut b = LinkedList::new();
+ b.push_back(5);
+ b.push_back(6);
+ a.extend(&b);
+
+ assert_eq!(a.len(), 6);
+ assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6]));
+}
+
+#[test]
+fn test_extend() {
+ let mut a = LinkedList::new();
+ a.push_back(1);
+ a.extend(vec![2, 3, 4]); // uses iterator
+
+ assert_eq!(a.len(), 4);
+ assert!(a.iter().eq(&[1, 2, 3, 4]));
+
+ let b: LinkedList<_> = vec![5, 6, 7].into_iter().collect();
+ a.extend(b); // specializes to `append`
+
+ assert_eq!(a.len(), 7);
+ assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7]));
+}
+
+#[test]
+fn test_contains() {
+ let mut l = LinkedList::new();
+ l.extend(&[2, 3, 4]);
+
+ assert!(l.contains(&3));
+ assert!(!l.contains(&1));
+
+ l.clear();
+
+ assert!(!l.contains(&3));
+}
--- /dev/null
+// 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.
+
+use std::cmp::Ordering::{Equal, Greater, Less};
+use std::mem;
+use std::__rand::{Rng, thread_rng};
+use std::rc::Rc;
+
+fn square(n: usize) -> usize {
+ n * n
+}
+
+fn is_odd(n: &usize) -> bool {
+ *n % 2 == 1
+}
+
+#[test]
+fn test_from_fn() {
+ // Test on-stack from_fn.
+ let mut v: Vec<_> = (0..3).map(square).collect();
+ {
+ let v = v;
+ assert_eq!(v.len(), 3);
+ assert_eq!(v[0], 0);
+ assert_eq!(v[1], 1);
+ assert_eq!(v[2], 4);
+ }
+
+ // Test on-heap from_fn.
+ v = (0..5).map(square).collect();
+ {
+ let v = v;
+ assert_eq!(v.len(), 5);
+ assert_eq!(v[0], 0);
+ assert_eq!(v[1], 1);
+ assert_eq!(v[2], 4);
+ assert_eq!(v[3], 9);
+ assert_eq!(v[4], 16);
+ }
+}
+
+#[test]
+fn test_from_elem() {
+ // Test on-stack from_elem.
+ let mut v = vec![10, 10];
+ {
+ let v = v;
+ assert_eq!(v.len(), 2);
+ assert_eq!(v[0], 10);
+ assert_eq!(v[1], 10);
+ }
+
+ // Test on-heap from_elem.
+ v = vec![20; 6];
+ {
+ let v = &v[..];
+ assert_eq!(v[0], 20);
+ assert_eq!(v[1], 20);
+ assert_eq!(v[2], 20);
+ assert_eq!(v[3], 20);
+ assert_eq!(v[4], 20);
+ assert_eq!(v[5], 20);
+ }
+}
+
+#[test]
+fn test_is_empty() {
+ let xs: [i32; 0] = [];
+ assert!(xs.is_empty());
+ assert!(![0].is_empty());
+}
+
+#[test]
+fn test_len_divzero() {
+ type Z = [i8; 0];
+ let v0: &[Z] = &[];
+ let v1: &[Z] = &[[]];
+ let v2: &[Z] = &[[], []];
+ assert_eq!(mem::size_of::<Z>(), 0);
+ assert_eq!(v0.len(), 0);
+ assert_eq!(v1.len(), 1);
+ assert_eq!(v2.len(), 2);
+}
+
+#[test]
+fn test_get() {
+ let mut a = vec![11];
+ assert_eq!(a.get(1), None);
+ a = vec![11, 12];
+ assert_eq!(a.get(1).unwrap(), &12);
+ a = vec![11, 12, 13];
+ assert_eq!(a.get(1).unwrap(), &12);
+}
+
+#[test]
+fn test_first() {
+ let mut a = vec![];
+ assert_eq!(a.first(), None);
+ a = vec![11];
+ assert_eq!(a.first().unwrap(), &11);
+ a = vec![11, 12];
+ assert_eq!(a.first().unwrap(), &11);
+}
+
+#[test]
+fn test_first_mut() {
+ let mut a = vec![];
+ assert_eq!(a.first_mut(), None);
+ a = vec![11];
+ assert_eq!(*a.first_mut().unwrap(), 11);
+ a = vec![11, 12];
+ assert_eq!(*a.first_mut().unwrap(), 11);
+}
+
+#[test]
+fn test_split_first() {
+ let mut a = vec![11];
+ let b: &[i32] = &[];
+ assert!(b.split_first().is_none());
+ assert_eq!(a.split_first(), Some((&11, b)));
+ a = vec![11, 12];
+ let b: &[i32] = &[12];
+ assert_eq!(a.split_first(), Some((&11, b)));
+}
+
+#[test]
+fn test_split_first_mut() {
+ let mut a = vec![11];
+ let b: &mut [i32] = &mut [];
+ assert!(b.split_first_mut().is_none());
+ assert!(a.split_first_mut() == Some((&mut 11, b)));
+ a = vec![11, 12];
+ let b: &mut [_] = &mut [12];
+ assert!(a.split_first_mut() == Some((&mut 11, b)));
+}
+
+#[test]
+fn test_split_last() {
+ let mut a = vec![11];
+ let b: &[i32] = &[];
+ assert!(b.split_last().is_none());
+ assert_eq!(a.split_last(), Some((&11, b)));
+ a = vec![11, 12];
+ let b: &[_] = &[11];
+ assert_eq!(a.split_last(), Some((&12, b)));
+}
+
+#[test]
+fn test_split_last_mut() {
+ let mut a = vec![11];
+ let b: &mut [i32] = &mut [];
+ assert!(b.split_last_mut().is_none());
+ assert!(a.split_last_mut() == Some((&mut 11, b)));
+
+ a = vec![11, 12];
+ let b: &mut [_] = &mut [11];
+ assert!(a.split_last_mut() == Some((&mut 12, b)));
+}
+
+#[test]
+fn test_last() {
+ let mut a = vec![];
+ assert_eq!(a.last(), None);
+ a = vec![11];
+ assert_eq!(a.last().unwrap(), &11);
+ a = vec![11, 12];
+ assert_eq!(a.last().unwrap(), &12);
+}
+
+#[test]
+fn test_last_mut() {
+ let mut a = vec![];
+ assert_eq!(a.last_mut(), None);
+ a = vec![11];
+ assert_eq!(*a.last_mut().unwrap(), 11);
+ a = vec![11, 12];
+ assert_eq!(*a.last_mut().unwrap(), 12);
+}
+
+#[test]
+fn test_slice() {
+ // Test fixed length vector.
+ let vec_fixed = [1, 2, 3, 4];
+ let v_a = vec_fixed[1..vec_fixed.len()].to_vec();
+ assert_eq!(v_a.len(), 3);
+
+ assert_eq!(v_a[0], 2);
+ assert_eq!(v_a[1], 3);
+ assert_eq!(v_a[2], 4);
+
+ // Test on stack.
+ let vec_stack: &[_] = &[1, 2, 3];
+ let v_b = vec_stack[1..3].to_vec();
+ assert_eq!(v_b.len(), 2);
+
+ assert_eq!(v_b[0], 2);
+ assert_eq!(v_b[1], 3);
+
+ // Test `Box<[T]>`
+ let vec_unique = vec![1, 2, 3, 4, 5, 6];
+ let v_d = vec_unique[1..6].to_vec();
+ assert_eq!(v_d.len(), 5);
+
+ assert_eq!(v_d[0], 2);
+ assert_eq!(v_d[1], 3);
+ assert_eq!(v_d[2], 4);
+ assert_eq!(v_d[3], 5);
+ assert_eq!(v_d[4], 6);
+}
+
+#[test]
+fn test_slice_from() {
+ let vec: &[_] = &[1, 2, 3, 4];
+ assert_eq!(&vec[..], vec);
+ let b: &[_] = &[3, 4];
+ assert_eq!(&vec[2..], b);
+ let b: &[_] = &[];
+ assert_eq!(&vec[4..], b);
+}
+
+#[test]
+fn test_slice_to() {
+ let vec: &[_] = &[1, 2, 3, 4];
+ assert_eq!(&vec[..4], vec);
+ let b: &[_] = &[1, 2];
+ assert_eq!(&vec[..2], b);
+ let b: &[_] = &[];
+ assert_eq!(&vec[..0], b);
+}
+
+
+#[test]
+fn test_pop() {
+ let mut v = vec![5];
+ let e = v.pop();
+ assert_eq!(v.len(), 0);
+ assert_eq!(e, Some(5));
+ let f = v.pop();
+ assert_eq!(f, None);
+ let g = v.pop();
+ assert_eq!(g, None);
+}
+
+#[test]
+fn test_swap_remove() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ let mut e = v.swap_remove(0);
+ assert_eq!(e, 1);
+ assert_eq!(v, [5, 2, 3, 4]);
+ e = v.swap_remove(3);
+ assert_eq!(e, 4);
+ assert_eq!(v, [5, 2, 3]);
+}
+
+#[test]
+#[should_panic]
+fn test_swap_remove_fail() {
+ let mut v = vec![1];
+ let _ = v.swap_remove(0);
+ let _ = v.swap_remove(0);
+}
+
+#[test]
+fn test_swap_remove_noncopyable() {
+ // Tests that we don't accidentally run destructors twice.
+ let mut v: Vec<Box<_>> = Vec::new();
+ v.push(box 0);
+ v.push(box 0);
+ v.push(box 0);
+ let mut _e = v.swap_remove(0);
+ assert_eq!(v.len(), 2);
+ _e = v.swap_remove(1);
+ assert_eq!(v.len(), 1);
+ _e = v.swap_remove(0);
+ assert_eq!(v.len(), 0);
+}
+
+#[test]
+fn test_push() {
+ // Test on-stack push().
+ let mut v = vec![];
+ v.push(1);
+ assert_eq!(v.len(), 1);
+ assert_eq!(v[0], 1);
+
+ // Test on-heap push().
+ v.push(2);
+ assert_eq!(v.len(), 2);
+ assert_eq!(v[0], 1);
+ assert_eq!(v[1], 2);
+}
+
+#[test]
+fn test_truncate() {
+ let mut v: Vec<Box<_>> = vec![box 6, box 5, box 4];
+ v.truncate(1);
+ let v = v;
+ assert_eq!(v.len(), 1);
+ assert_eq!(*(v[0]), 6);
+ // If the unsafe block didn't drop things properly, we blow up here.
+}
+
+#[test]
+fn test_clear() {
+ let mut v: Vec<Box<_>> = vec![box 6, box 5, box 4];
+ v.clear();
+ assert_eq!(v.len(), 0);
+ // If the unsafe block didn't drop things properly, we blow up here.
+}
+
+#[test]
+fn test_retain() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ v.retain(is_odd);
+ assert_eq!(v, [1, 3, 5]);
+}
+
+#[test]
+fn test_binary_search() {
+ assert_eq!([1, 2, 3, 4, 5].binary_search(&5).ok(), Some(4));
+ assert_eq!([1, 2, 3, 4, 5].binary_search(&4).ok(), Some(3));
+ assert_eq!([1, 2, 3, 4, 5].binary_search(&3).ok(), Some(2));
+ assert_eq!([1, 2, 3, 4, 5].binary_search(&2).ok(), Some(1));
+ assert_eq!([1, 2, 3, 4, 5].binary_search(&1).ok(), Some(0));
+
+ assert_eq!([2, 4, 6, 8, 10].binary_search(&1).ok(), None);
+ assert_eq!([2, 4, 6, 8, 10].binary_search(&5).ok(), None);
+ assert_eq!([2, 4, 6, 8, 10].binary_search(&4).ok(), Some(1));
+ assert_eq!([2, 4, 6, 8, 10].binary_search(&10).ok(), Some(4));
+
+ assert_eq!([2, 4, 6, 8].binary_search(&1).ok(), None);
+ assert_eq!([2, 4, 6, 8].binary_search(&5).ok(), None);
+ assert_eq!([2, 4, 6, 8].binary_search(&4).ok(), Some(1));
+ assert_eq!([2, 4, 6, 8].binary_search(&8).ok(), Some(3));
+
+ assert_eq!([2, 4, 6].binary_search(&1).ok(), None);
+ assert_eq!([2, 4, 6].binary_search(&5).ok(), None);
+ assert_eq!([2, 4, 6].binary_search(&4).ok(), Some(1));
+ assert_eq!([2, 4, 6].binary_search(&6).ok(), Some(2));
+
+ assert_eq!([2, 4].binary_search(&1).ok(), None);
+ assert_eq!([2, 4].binary_search(&5).ok(), None);
+ assert_eq!([2, 4].binary_search(&2).ok(), Some(0));
+ assert_eq!([2, 4].binary_search(&4).ok(), Some(1));
+
+ assert_eq!([2].binary_search(&1).ok(), None);
+ assert_eq!([2].binary_search(&5).ok(), None);
+ assert_eq!([2].binary_search(&2).ok(), Some(0));
+
+ assert_eq!([].binary_search(&1).ok(), None);
+ assert_eq!([].binary_search(&5).ok(), None);
+
+ assert!([1, 1, 1, 1, 1].binary_search(&1).ok() != None);
+ assert!([1, 1, 1, 1, 2].binary_search(&1).ok() != None);
+ assert!([1, 1, 1, 2, 2].binary_search(&1).ok() != None);
+ assert!([1, 1, 2, 2, 2].binary_search(&1).ok() != None);
+ assert_eq!([1, 2, 2, 2, 2].binary_search(&1).ok(), Some(0));
+
+ assert_eq!([1, 2, 3, 4, 5].binary_search(&6).ok(), None);
+ assert_eq!([1, 2, 3, 4, 5].binary_search(&0).ok(), None);
+}
+
+#[test]
+fn test_reverse() {
+ let mut v = vec![10, 20];
+ assert_eq!(v[0], 10);
+ assert_eq!(v[1], 20);
+ v.reverse();
+ assert_eq!(v[0], 20);
+ assert_eq!(v[1], 10);
+
+ let mut v3 = Vec::<i32>::new();
+ v3.reverse();
+ assert!(v3.is_empty());
+}
+
+#[test]
+fn test_sort() {
+ let mut rng = thread_rng();
+
+ for len in (2..25).chain(500..510) {
+ for _ in 0..100 {
+ let mut v: Vec<_> = rng.gen_iter::<i32>().take(len).collect();
+ let mut v1 = v.clone();
+
+ v.sort();
+ assert!(v.windows(2).all(|w| w[0] <= w[1]));
+
+ v1.sort_by(|a, b| a.cmp(b));
+ assert!(v1.windows(2).all(|w| w[0] <= w[1]));
+
+ v1.sort_by(|a, b| b.cmp(a));
+ assert!(v1.windows(2).all(|w| w[0] >= w[1]));
+ }
+ }
+
+ // Sort using a completely random comparison function.
+ // This will reorder the elements *somehow*, but won't panic.
+ let mut v = [0; 500];
+ for i in 0..v.len() {
+ v[i] = i as i32;
+ }
+ v.sort_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap());
+ v.sort();
+ for i in 0..v.len() {
+ assert_eq!(v[i], i as i32);
+ }
+
+ // Should not panic.
+ [0i32; 0].sort();
+ [(); 10].sort();
+ [(); 100].sort();
+
+ let mut v = [0xDEADBEEFu64];
+ v.sort();
+ assert!(v == [0xDEADBEEF]);
+}
+
+#[test]
+fn test_sort_stability() {
+ for len in (2..25).chain(500..510) {
+ for _ in 0..10 {
+ let mut counts = [0; 10];
+
+ // create a vector like [(6, 1), (5, 1), (6, 2), ...],
+ // where the first item of each tuple is random, but
+ // the second item represents which occurrence of that
+ // number this element is, i.e. the second elements
+ // will occur in sorted order.
+ let mut v: Vec<_> = (0..len)
+ .map(|_| {
+ let n = thread_rng().gen::<usize>() % 10;
+ counts[n] += 1;
+ (n, counts[n])
+ })
+ .collect();
+
+ // only sort on the first element, so an unstable sort
+ // may mix up the counts.
+ v.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
+
+ // this comparison includes the count (the second item
+ // of the tuple), so elements with equal first items
+ // will need to be ordered with increasing
+ // counts... i.e. exactly asserting that this sort is
+ // stable.
+ assert!(v.windows(2).all(|w| w[0] <= w[1]));
+ }
+ }
+}
+
+#[test]
+fn test_concat() {
+ let v: [Vec<i32>; 0] = [];
+ let c = v.concat();
+ assert_eq!(c, []);
+ let d = [vec![1], vec![2, 3]].concat();
+ assert_eq!(d, [1, 2, 3]);
+
+ let v: &[&[_]] = &[&[1], &[2, 3]];
+ assert_eq!(v.join(&0), [1, 0, 2, 3]);
+ let v: &[&[_]] = &[&[1], &[2], &[3]];
+ assert_eq!(v.join(&0), [1, 0, 2, 0, 3]);
+}
+
+#[test]
+fn test_join() {
+ let v: [Vec<i32>; 0] = [];
+ assert_eq!(v.join(&0), []);
+ assert_eq!([vec![1], vec![2, 3]].join(&0), [1, 0, 2, 3]);
+ assert_eq!([vec![1], vec![2], vec![3]].join(&0), [1, 0, 2, 0, 3]);
+
+ let v: [&[_]; 2] = [&[1], &[2, 3]];
+ assert_eq!(v.join(&0), [1, 0, 2, 3]);
+ let v: [&[_]; 3] = [&[1], &[2], &[3]];
+ assert_eq!(v.join(&0), [1, 0, 2, 0, 3]);
+}
+
+#[test]
+fn test_insert() {
+ let mut a = vec![1, 2, 4];
+ a.insert(2, 3);
+ assert_eq!(a, [1, 2, 3, 4]);
+
+ let mut a = vec![1, 2, 3];
+ a.insert(0, 0);
+ assert_eq!(a, [0, 1, 2, 3]);
+
+ let mut a = vec![1, 2, 3];
+ a.insert(3, 4);
+ assert_eq!(a, [1, 2, 3, 4]);
+
+ let mut a = vec![];
+ a.insert(0, 1);
+ assert_eq!(a, [1]);
+}
+
+#[test]
+#[should_panic]
+fn test_insert_oob() {
+ let mut a = vec![1, 2, 3];
+ a.insert(4, 5);
+}
+
+#[test]
+fn test_remove() {
+ let mut a = vec![1, 2, 3, 4];
+
+ assert_eq!(a.remove(2), 3);
+ assert_eq!(a, [1, 2, 4]);
+
+ assert_eq!(a.remove(2), 4);
+ assert_eq!(a, [1, 2]);
+
+ assert_eq!(a.remove(0), 1);
+ assert_eq!(a, [2]);
+
+ assert_eq!(a.remove(0), 2);
+ assert_eq!(a, []);
+}
+
+#[test]
+#[should_panic]
+fn test_remove_fail() {
+ let mut a = vec![1];
+ let _ = a.remove(0);
+ let _ = a.remove(0);
+}
+
+#[test]
+fn test_capacity() {
+ let mut v = vec![0];
+ v.reserve_exact(10);
+ assert!(v.capacity() >= 11);
+}
+
+#[test]
+fn test_slice_2() {
+ let v = vec![1, 2, 3, 4, 5];
+ let v = &v[1..3];
+ assert_eq!(v.len(), 2);
+ assert_eq!(v[0], 2);
+ assert_eq!(v[1], 3);
+}
+
+macro_rules! assert_order {
+ (Greater, $a:expr, $b:expr) => {
+ assert_eq!($a.cmp($b), Greater);
+ assert!($a > $b);
+ };
+ (Less, $a:expr, $b:expr) => {
+ assert_eq!($a.cmp($b), Less);
+ assert!($a < $b);
+ };
+ (Equal, $a:expr, $b:expr) => {
+ assert_eq!($a.cmp($b), Equal);
+ assert_eq!($a, $b);
+ }
+}
+
+#[test]
+fn test_total_ord_u8() {
+ let c = &[1u8, 2, 3];
+ assert_order!(Greater, &[1u8, 2, 3, 4][..], &c[..]);
+ let c = &[1u8, 2, 3, 4];
+ assert_order!(Less, &[1u8, 2, 3][..], &c[..]);
+ let c = &[1u8, 2, 3, 6];
+ assert_order!(Equal, &[1u8, 2, 3, 6][..], &c[..]);
+ let c = &[1u8, 2, 3, 4, 5, 6];
+ assert_order!(Less, &[1u8, 2, 3, 4, 5, 5, 5, 5][..], &c[..]);
+ let c = &[1u8, 2, 3, 4];
+ assert_order!(Greater, &[2u8, 2][..], &c[..]);
+}
+
+
+#[test]
+fn test_total_ord_i32() {
+ let c = &[1, 2, 3];
+ assert_order!(Greater, &[1, 2, 3, 4][..], &c[..]);
+ let c = &[1, 2, 3, 4];
+ assert_order!(Less, &[1, 2, 3][..], &c[..]);
+ let c = &[1, 2, 3, 6];
+ assert_order!(Equal, &[1, 2, 3, 6][..], &c[..]);
+ let c = &[1, 2, 3, 4, 5, 6];
+ assert_order!(Less, &[1, 2, 3, 4, 5, 5, 5, 5][..], &c[..]);
+ let c = &[1, 2, 3, 4];
+ assert_order!(Greater, &[2, 2][..], &c[..]);
+}
+
+#[test]
+fn test_iterator() {
+ let xs = [1, 2, 5, 10, 11];
+ let mut it = xs.iter();
+ assert_eq!(it.size_hint(), (5, Some(5)));
+ assert_eq!(it.next().unwrap(), &1);
+ assert_eq!(it.size_hint(), (4, Some(4)));
+ assert_eq!(it.next().unwrap(), &2);
+ assert_eq!(it.size_hint(), (3, Some(3)));
+ assert_eq!(it.next().unwrap(), &5);
+ assert_eq!(it.size_hint(), (2, Some(2)));
+ assert_eq!(it.next().unwrap(), &10);
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(it.next().unwrap(), &11);
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert!(it.next().is_none());
+}
+
+#[test]
+fn test_iter_size_hints() {
+ let mut xs = [1, 2, 5, 10, 11];
+ assert_eq!(xs.iter().size_hint(), (5, Some(5)));
+ assert_eq!(xs.iter_mut().size_hint(), (5, Some(5)));
+}
+
+#[test]
+fn test_iter_as_slice() {
+ let xs = [1, 2, 5, 10, 11];
+ let mut iter = xs.iter();
+ assert_eq!(iter.as_slice(), &[1, 2, 5, 10, 11]);
+ iter.next();
+ assert_eq!(iter.as_slice(), &[2, 5, 10, 11]);
+}
+
+#[test]
+fn test_iter_as_ref() {
+ let xs = [1, 2, 5, 10, 11];
+ let mut iter = xs.iter();
+ assert_eq!(iter.as_ref(), &[1, 2, 5, 10, 11]);
+ iter.next();
+ assert_eq!(iter.as_ref(), &[2, 5, 10, 11]);
+}
+
+#[test]
+fn test_iter_clone() {
+ let xs = [1, 2, 5];
+ let mut it = xs.iter();
+ it.next();
+ let mut jt = it.clone();
+ assert_eq!(it.next(), jt.next());
+ assert_eq!(it.next(), jt.next());
+ assert_eq!(it.next(), jt.next());
+}
+
+#[test]
+fn test_iter_is_empty() {
+ let xs = [1, 2, 5, 10, 11];
+ for i in 0..xs.len() {
+ for j in i..xs.len() {
+ assert_eq!(xs[i..j].iter().is_empty(), xs[i..j].is_empty());
+ }
+ }
+}
+
+#[test]
+fn test_mut_iterator() {
+ let mut xs = [1, 2, 3, 4, 5];
+ for x in &mut xs {
+ *x += 1;
+ }
+ assert!(xs == [2, 3, 4, 5, 6])
+}
+
+#[test]
+fn test_rev_iterator() {
+
+ let xs = [1, 2, 5, 10, 11];
+ let ys = [11, 10, 5, 2, 1];
+ let mut i = 0;
+ for &x in xs.iter().rev() {
+ assert_eq!(x, ys[i]);
+ i += 1;
+ }
+ assert_eq!(i, 5);
+}
+
+#[test]
+fn test_mut_rev_iterator() {
+ let mut xs = [1, 2, 3, 4, 5];
+ for (i, x) in xs.iter_mut().rev().enumerate() {
+ *x += i;
+ }
+ assert!(xs == [5, 5, 5, 5, 5])
+}
+
+#[test]
+fn test_move_iterator() {
+ let xs = vec![1, 2, 3, 4, 5];
+ assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10 * a + b),
+ 12345);
+}
+
+#[test]
+fn test_move_rev_iterator() {
+ let xs = vec![1, 2, 3, 4, 5];
+ assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10 * a + b),
+ 54321);
+}
+
+#[test]
+fn test_splitator() {
+ let xs = &[1, 2, 3, 4, 5];
+
+ let splits: &[&[_]] = &[&[1], &[3], &[5]];
+ assert_eq!(xs.split(|x| *x % 2 == 0).collect::<Vec<_>>(), splits);
+ let splits: &[&[_]] = &[&[], &[2, 3, 4, 5]];
+ assert_eq!(xs.split(|x| *x == 1).collect::<Vec<_>>(), splits);
+ let splits: &[&[_]] = &[&[1, 2, 3, 4], &[]];
+ assert_eq!(xs.split(|x| *x == 5).collect::<Vec<_>>(), splits);
+ let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+ assert_eq!(xs.split(|x| *x == 10).collect::<Vec<_>>(), splits);
+ let splits: &[&[_]] = &[&[], &[], &[], &[], &[], &[]];
+ assert_eq!(xs.split(|_| true).collect::<Vec<&[i32]>>(), splits);
+
+ let xs: &[i32] = &[];
+ let splits: &[&[i32]] = &[&[]];
+ assert_eq!(xs.split(|x| *x == 5).collect::<Vec<&[i32]>>(), splits);
+}
+
+#[test]
+fn test_splitnator() {
+ let xs = &[1, 2, 3, 4, 5];
+
+ let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+ assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(), splits);
+ let splits: &[&[_]] = &[&[1], &[3, 4, 5]];
+ assert_eq!(xs.splitn(2, |x| *x % 2 == 0).collect::<Vec<_>>(), splits);
+ let splits: &[&[_]] = &[&[], &[], &[], &[4, 5]];
+ assert_eq!(xs.splitn(4, |_| true).collect::<Vec<_>>(), splits);
+
+ let xs: &[i32] = &[];
+ let splits: &[&[i32]] = &[&[]];
+ assert_eq!(xs.splitn(2, |x| *x == 5).collect::<Vec<_>>(), splits);
+}
+
+#[test]
+fn test_splitnator_mut() {
+ let xs = &mut [1, 2, 3, 4, 5];
+
+ let splits: &[&mut [_]] = &[&mut [1, 2, 3, 4, 5]];
+ assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
+ splits);
+ let splits: &[&mut [_]] = &[&mut [1], &mut [3, 4, 5]];
+ assert_eq!(xs.splitn_mut(2, |x| *x % 2 == 0).collect::<Vec<_>>(),
+ splits);
+ let splits: &[&mut [_]] = &[&mut [], &mut [], &mut [], &mut [4, 5]];
+ assert_eq!(xs.splitn_mut(4, |_| true).collect::<Vec<_>>(), splits);
+
+ let xs: &mut [i32] = &mut [];
+ let splits: &[&mut [i32]] = &[&mut []];
+ assert_eq!(xs.splitn_mut(2, |x| *x == 5).collect::<Vec<_>>(), splits);
+}
+
+#[test]
+fn test_rsplitator() {
+ let xs = &[1, 2, 3, 4, 5];
+
+ let splits: &[&[_]] = &[&[5], &[3], &[1]];
+ assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits);
+ let splits: &[&[_]] = &[&[2, 3, 4, 5], &[]];
+ assert_eq!(xs.split(|x| *x == 1).rev().collect::<Vec<_>>(), splits);
+ let splits: &[&[_]] = &[&[], &[1, 2, 3, 4]];
+ assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
+ let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+ assert_eq!(xs.split(|x| *x == 10).rev().collect::<Vec<_>>(), splits);
+
+ let xs: &[i32] = &[];
+ let splits: &[&[i32]] = &[&[]];
+ assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<&[i32]>>(), splits);
+}
+
+#[test]
+fn test_rsplitnator() {
+ let xs = &[1, 2, 3, 4, 5];
+
+ let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+ assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(), splits);
+ let splits: &[&[_]] = &[&[5], &[1, 2, 3]];
+ assert_eq!(xs.rsplitn(2, |x| *x % 2 == 0).collect::<Vec<_>>(), splits);
+ let splits: &[&[_]] = &[&[], &[], &[], &[1, 2]];
+ assert_eq!(xs.rsplitn(4, |_| true).collect::<Vec<_>>(), splits);
+
+ let xs: &[i32] = &[];
+ let splits: &[&[i32]] = &[&[]];
+ assert_eq!(xs.rsplitn(2, |x| *x == 5).collect::<Vec<&[i32]>>(), splits);
+ assert!(xs.rsplitn(0, |x| *x % 2 == 0).next().is_none());
+}
+
+#[test]
+fn test_windowsator() {
+ let v = &[1, 2, 3, 4];
+
+ let wins: &[&[_]] = &[&[1, 2], &[2, 3], &[3, 4]];
+ assert_eq!(v.windows(2).collect::<Vec<_>>(), wins);
+
+ let wins: &[&[_]] = &[&[1, 2, 3], &[2, 3, 4]];
+ assert_eq!(v.windows(3).collect::<Vec<_>>(), wins);
+ assert!(v.windows(6).next().is_none());
+
+ let wins: &[&[_]] = &[&[3, 4], &[2, 3], &[1, 2]];
+ assert_eq!(v.windows(2).rev().collect::<Vec<&[_]>>(), wins);
+}
+
+#[test]
+#[should_panic]
+fn test_windowsator_0() {
+ let v = &[1, 2, 3, 4];
+ let _it = v.windows(0);
+}
+
+#[test]
+fn test_chunksator() {
+ let v = &[1, 2, 3, 4, 5];
+
+ assert_eq!(v.chunks(2).len(), 3);
+
+ let chunks: &[&[_]] = &[&[1, 2], &[3, 4], &[5]];
+ assert_eq!(v.chunks(2).collect::<Vec<_>>(), chunks);
+ let chunks: &[&[_]] = &[&[1, 2, 3], &[4, 5]];
+ assert_eq!(v.chunks(3).collect::<Vec<_>>(), chunks);
+ let chunks: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+ assert_eq!(v.chunks(6).collect::<Vec<_>>(), chunks);
+
+ let chunks: &[&[_]] = &[&[5], &[3, 4], &[1, 2]];
+ assert_eq!(v.chunks(2).rev().collect::<Vec<_>>(), chunks);
+}
+
+#[test]
+#[should_panic]
+fn test_chunksator_0() {
+ let v = &[1, 2, 3, 4];
+ let _it = v.chunks(0);
+}
+
+#[test]
+fn test_reverse_part() {
+ let mut values = [1, 2, 3, 4, 5];
+ values[1..4].reverse();
+ assert!(values == [1, 4, 3, 2, 5]);
+}
+
+#[test]
+fn test_show() {
+ macro_rules! test_show_vec {
+ ($x:expr, $x_str:expr) => ({
+ let (x, x_str) = ($x, $x_str);
+ assert_eq!(format!("{:?}", x), x_str);
+ assert_eq!(format!("{:?}", x), x_str);
+ })
+ }
+ let empty = Vec::<i32>::new();
+ test_show_vec!(empty, "[]");
+ test_show_vec!(vec![1], "[1]");
+ test_show_vec!(vec![1, 2, 3], "[1, 2, 3]");
+ test_show_vec!(vec![vec![], vec![1], vec![1, 1]], "[[], [1], [1, 1]]");
+
+ let empty_mut: &mut [i32] = &mut [];
+ test_show_vec!(empty_mut, "[]");
+ let v = &mut [1];
+ test_show_vec!(v, "[1]");
+ let v = &mut [1, 2, 3];
+ test_show_vec!(v, "[1, 2, 3]");
+ let v: &mut [&mut [_]] = &mut [&mut [], &mut [1], &mut [1, 1]];
+ test_show_vec!(v, "[[], [1], [1, 1]]");
+}
+
+#[test]
+fn test_vec_default() {
+ macro_rules! t {
+ ($ty:ty) => {{
+ let v: $ty = Default::default();
+ assert!(v.is_empty());
+ }}
+ }
+
+ t!(&[i32]);
+ t!(Vec<i32>);
+}
+
+#[test]
+#[should_panic]
+fn test_overflow_does_not_cause_segfault() {
+ let mut v = vec![];
+ v.reserve_exact(!0);
+ v.push(1);
+ v.push(2);
+}
+
+#[test]
+#[should_panic]
+fn test_overflow_does_not_cause_segfault_managed() {
+ let mut v = vec![Rc::new(1)];
+ v.reserve_exact(!0);
+ v.push(Rc::new(2));
+}
+
+#[test]
+fn test_mut_split_at() {
+ let mut values = [1, 2, 3, 4, 5];
+ {
+ let (left, right) = values.split_at_mut(2);
+ {
+ let left: &[_] = left;
+ assert!(left[..left.len()] == [1, 2]);
+ }
+ for p in left {
+ *p += 1;
+ }
+
+ {
+ let right: &[_] = right;
+ assert!(right[..right.len()] == [3, 4, 5]);
+ }
+ for p in right {
+ *p += 2;
+ }
+ }
+
+ assert!(values == [2, 3, 5, 6, 7]);
+}
+
+#[derive(Clone, PartialEq)]
+struct Foo;
+
+#[test]
+fn test_iter_zero_sized() {
+ let mut v = vec![Foo, Foo, Foo];
+ assert_eq!(v.len(), 3);
+ let mut cnt = 0;
+
+ for f in &v {
+ assert!(*f == Foo);
+ cnt += 1;
+ }
+ assert_eq!(cnt, 3);
+
+ for f in &v[1..3] {
+ assert!(*f == Foo);
+ cnt += 1;
+ }
+ assert_eq!(cnt, 5);
+
+ for f in &mut v {
+ assert!(*f == Foo);
+ cnt += 1;
+ }
+ assert_eq!(cnt, 8);
+
+ for f in v {
+ assert!(f == Foo);
+ cnt += 1;
+ }
+ assert_eq!(cnt, 11);
+
+ let xs: [Foo; 3] = [Foo, Foo, Foo];
+ cnt = 0;
+ for f in &xs {
+ assert!(*f == Foo);
+ cnt += 1;
+ }
+ assert!(cnt == 3);
+}
+
+#[test]
+fn test_shrink_to_fit() {
+ let mut xs = vec![0, 1, 2, 3];
+ for i in 4..100 {
+ xs.push(i)
+ }
+ assert_eq!(xs.capacity(), 128);
+ xs.shrink_to_fit();
+ assert_eq!(xs.capacity(), 100);
+ assert_eq!(xs, (0..100).collect::<Vec<_>>());
+}
+
+#[test]
+fn test_starts_with() {
+ assert!(b"foobar".starts_with(b"foo"));
+ assert!(!b"foobar".starts_with(b"oob"));
+ assert!(!b"foobar".starts_with(b"bar"));
+ assert!(!b"foo".starts_with(b"foobar"));
+ assert!(!b"bar".starts_with(b"foobar"));
+ assert!(b"foobar".starts_with(b"foobar"));
+ let empty: &[u8] = &[];
+ assert!(empty.starts_with(empty));
+ assert!(!empty.starts_with(b"foo"));
+ assert!(b"foobar".starts_with(empty));
+}
+
+#[test]
+fn test_ends_with() {
+ assert!(b"foobar".ends_with(b"bar"));
+ assert!(!b"foobar".ends_with(b"oba"));
+ assert!(!b"foobar".ends_with(b"foo"));
+ assert!(!b"foo".ends_with(b"foobar"));
+ assert!(!b"bar".ends_with(b"foobar"));
+ assert!(b"foobar".ends_with(b"foobar"));
+ let empty: &[u8] = &[];
+ assert!(empty.ends_with(empty));
+ assert!(!empty.ends_with(b"foo"));
+ assert!(b"foobar".ends_with(empty));
+}
+
+#[test]
+fn test_mut_splitator() {
+ let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0];
+ assert_eq!(xs.split_mut(|x| *x == 0).count(), 6);
+ for slice in xs.split_mut(|x| *x == 0) {
+ slice.reverse();
+ }
+ assert!(xs == [0, 1, 0, 3, 2, 0, 0, 5, 4, 0]);
+
+ let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0, 6, 7];
+ for slice in xs.split_mut(|x| *x == 0).take(5) {
+ slice.reverse();
+ }
+ assert!(xs == [0, 1, 0, 3, 2, 0, 0, 5, 4, 0, 6, 7]);
+}
+
+#[test]
+fn test_mut_splitator_rev() {
+ let mut xs = [1, 2, 0, 3, 4, 0, 0, 5, 6, 0];
+ for slice in xs.split_mut(|x| *x == 0).rev().take(4) {
+ slice.reverse();
+ }
+ assert!(xs == [1, 2, 0, 4, 3, 0, 0, 6, 5, 0]);
+}
+
+#[test]
+fn test_get_mut() {
+ let mut v = [0, 1, 2];
+ assert_eq!(v.get_mut(3), None);
+ v.get_mut(1).map(|e| *e = 7);
+ assert_eq!(v[1], 7);
+ let mut x = 2;
+ assert_eq!(v.get_mut(2), Some(&mut x));
+}
+
+#[test]
+fn test_mut_chunks() {
+ let mut v = [0, 1, 2, 3, 4, 5, 6];
+ assert_eq!(v.chunks_mut(2).len(), 4);
+ for (i, chunk) in v.chunks_mut(3).enumerate() {
+ for x in chunk {
+ *x = i as u8;
+ }
+ }
+ let result = [0, 0, 0, 1, 1, 1, 2];
+ assert!(v == result);
+}
+
+#[test]
+fn test_mut_chunks_rev() {
+ let mut v = [0, 1, 2, 3, 4, 5, 6];
+ for (i, chunk) in v.chunks_mut(3).rev().enumerate() {
+ for x in chunk {
+ *x = i as u8;
+ }
+ }
+ let result = [2, 2, 2, 1, 1, 1, 0];
+ assert!(v == result);
+}
+
+#[test]
+#[should_panic]
+fn test_mut_chunks_0() {
+ let mut v = [1, 2, 3, 4];
+ let _it = v.chunks_mut(0);
+}
+
+#[test]
+fn test_mut_last() {
+ let mut x = [1, 2, 3, 4, 5];
+ let h = x.last_mut();
+ assert_eq!(*h.unwrap(), 5);
+
+ let y: &mut [i32] = &mut [];
+ assert!(y.last_mut().is_none());
+}
+
+#[test]
+fn test_to_vec() {
+ let xs: Box<_> = box [1, 2, 3];
+ let ys = xs.to_vec();
+ assert_eq!(ys, [1, 2, 3]);
+}
+
+#[test]
+fn test_box_slice_clone() {
+ let data = vec![vec![0, 1], vec![0], vec![1]];
+ let data2 = data.clone().into_boxed_slice().clone().to_vec();
+
+ assert_eq!(data, data2);
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_box_slice_clone_panics() {
+ use std::sync::Arc;
+ use std::sync::atomic::{AtomicUsize, Ordering};
+ use std::thread::spawn;
+
+ struct Canary {
+ count: Arc<AtomicUsize>,
+ panics: bool,
+ }
+
+ impl Drop for Canary {
+ fn drop(&mut self) {
+ self.count.fetch_add(1, Ordering::SeqCst);
+ }
+ }
+
+ impl Clone for Canary {
+ fn clone(&self) -> Self {
+ if self.panics {
+ panic!()
+ }
+
+ Canary {
+ count: self.count.clone(),
+ panics: self.panics,
+ }
+ }
+ }
+
+ let drop_count = Arc::new(AtomicUsize::new(0));
+ let canary = Canary {
+ count: drop_count.clone(),
+ panics: false,
+ };
+ let panic = Canary {
+ count: drop_count.clone(),
+ panics: true,
+ };
+
+ spawn(move || {
+ // When xs is dropped, +5.
+ let xs = vec![canary.clone(), canary.clone(), canary.clone(), panic, canary]
+ .into_boxed_slice();
+
+ // When panic is cloned, +3.
+ xs.clone();
+ })
+ .join()
+ .unwrap_err();
+
+ // Total = 8
+ assert_eq!(drop_count.load(Ordering::SeqCst), 8);
+}
+
+#[test]
+fn test_copy_from_slice() {
+ let src = [0, 1, 2, 3, 4, 5];
+ let mut dst = [0; 6];
+ dst.copy_from_slice(&src);
+ assert_eq!(src, dst)
+}
+
+#[test]
+#[should_panic(expected = "destination and source slices have different lengths")]
+fn test_copy_from_slice_dst_longer() {
+ let src = [0, 1, 2, 3];
+ let mut dst = [0; 5];
+ dst.copy_from_slice(&src);
+}
+
+#[test]
+#[should_panic(expected = "destination and source slices have different lengths")]
+fn test_copy_from_slice_dst_shorter() {
+ let src = [0, 1, 2, 3];
+ let mut dst = [0; 3];
+ dst.copy_from_slice(&src);
+}
--- /dev/null
+// 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.
+
+use std::borrow::Cow;
+use std::cmp::Ordering::{Equal, Greater, Less};
+use std::str::from_utf8;
+
+#[test]
+fn test_le() {
+ assert!("" <= "");
+ assert!("" <= "foo");
+ assert!("foo" <= "foo");
+ assert!("foo" != "bar");
+}
+
+#[test]
+fn test_find() {
+ assert_eq!("hello".find('l'), Some(2));
+ assert_eq!("hello".find(|c:char| c == 'o'), Some(4));
+ assert!("hello".find('x').is_none());
+ assert!("hello".find(|c:char| c == 'x').is_none());
+ assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
+ assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
+}
+
+#[test]
+fn test_rfind() {
+ assert_eq!("hello".rfind('l'), Some(3));
+ assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4));
+ assert!("hello".rfind('x').is_none());
+ assert!("hello".rfind(|c:char| c == 'x').is_none());
+ assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
+ assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
+}
+
+#[test]
+fn test_collect() {
+ let empty = "";
+ let s: String = empty.chars().collect();
+ assert_eq!(empty, s);
+ let data = "ประเทศไทย中";
+ let s: String = data.chars().collect();
+ assert_eq!(data, s);
+}
+
+#[test]
+fn test_into_bytes() {
+ let data = String::from("asdf");
+ let buf = data.into_bytes();
+ assert_eq!(buf, b"asdf");
+}
+
+#[test]
+fn test_find_str() {
+ // byte positions
+ assert_eq!("".find(""), Some(0));
+ assert!("banana".find("apple pie").is_none());
+
+ let data = "abcabc";
+ assert_eq!(data[0..6].find("ab"), Some(0));
+ assert_eq!(data[2..6].find("ab"), Some(3 - 2));
+ assert!(data[2..4].find("ab").is_none());
+
+ let string = "ประเทศไทย中华Việt Nam";
+ let mut data = String::from(string);
+ data.push_str(string);
+ assert!(data.find("ไท华").is_none());
+ assert_eq!(data[0..43].find(""), Some(0));
+ assert_eq!(data[6..43].find(""), Some(6 - 6));
+
+ assert_eq!(data[0..43].find("ประ"), Some( 0));
+ assert_eq!(data[0..43].find("ทศไ"), Some(12));
+ assert_eq!(data[0..43].find("ย中"), Some(24));
+ assert_eq!(data[0..43].find("iệt"), Some(34));
+ assert_eq!(data[0..43].find("Nam"), Some(40));
+
+ assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
+ assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
+ assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
+ assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
+ assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
+
+ // find every substring -- assert that it finds it, or an earlier occurrence.
+ let string = "Việt Namacbaabcaabaaba";
+ for (i, ci) in string.char_indices() {
+ let ip = i + ci.len_utf8();
+ for j in string[ip..].char_indices()
+ .map(|(i, _)| i)
+ .chain(Some(string.len() - ip))
+ {
+ let pat = &string[i..ip + j];
+ assert!(match string.find(pat) {
+ None => false,
+ Some(x) => x <= i,
+ });
+ assert!(match string.rfind(pat) {
+ None => false,
+ Some(x) => x >= i,
+ });
+ }
+ }
+}
+
+fn s(x: &str) -> String { x.to_string() }
+
+macro_rules! test_concat {
+ ($expected: expr, $string: expr) => {
+ {
+ let s: String = $string.concat();
+ assert_eq!($expected, s);
+ }
+ }
+}
+
+#[test]
+fn test_concat_for_different_types() {
+ test_concat!("ab", vec![s("a"), s("b")]);
+ test_concat!("ab", vec!["a", "b"]);
+}
+
+#[test]
+fn test_concat_for_different_lengths() {
+ let empty: &[&str] = &[];
+ test_concat!("", empty);
+ test_concat!("a", ["a"]);
+ test_concat!("ab", ["a", "b"]);
+ test_concat!("abc", ["", "a", "bc"]);
+}
+
+macro_rules! test_join {
+ ($expected: expr, $string: expr, $delim: expr) => {
+ {
+ let s = $string.join($delim);
+ assert_eq!($expected, s);
+ }
+ }
+}
+
+#[test]
+fn test_join_for_different_types() {
+ test_join!("a-b", ["a", "b"], "-");
+ let hyphen = "-".to_string();
+ test_join!("a-b", [s("a"), s("b")], &*hyphen);
+ test_join!("a-b", vec!["a", "b"], &*hyphen);
+ test_join!("a-b", &*vec!["a", "b"], "-");
+ test_join!("a-b", vec![s("a"), s("b")], "-");
+}
+
+#[test]
+fn test_join_for_different_lengths() {
+ let empty: &[&str] = &[];
+ test_join!("", empty, "-");
+ test_join!("a", ["a"], "-");
+ test_join!("a-b", ["a", "b"], "-");
+ test_join!("-a-bc", ["", "a", "bc"], "-");
+}
+
+#[test]
+fn test_unsafe_slice() {
+ assert_eq!("ab", unsafe {"abc".slice_unchecked(0, 2)});
+ assert_eq!("bc", unsafe {"abc".slice_unchecked(1, 3)});
+ assert_eq!("", unsafe {"abc".slice_unchecked(1, 1)});
+ fn a_million_letter_a() -> String {
+ let mut i = 0;
+ let mut rs = String::new();
+ while i < 100000 {
+ rs.push_str("aaaaaaaaaa");
+ i += 1;
+ }
+ rs
+ }
+ fn half_a_million_letter_a() -> String {
+ let mut i = 0;
+ let mut rs = String::new();
+ while i < 100000 {
+ rs.push_str("aaaaa");
+ i += 1;
+ }
+ rs
+ }
+ let letters = a_million_letter_a();
+ assert_eq!(half_a_million_letter_a(),
+ unsafe { letters.slice_unchecked(0, 500000)});
+}
+
+#[test]
+fn test_starts_with() {
+ assert!("".starts_with(""));
+ assert!("abc".starts_with(""));
+ assert!("abc".starts_with("a"));
+ assert!(!"a".starts_with("abc"));
+ assert!(!"".starts_with("abc"));
+ assert!(!"ödd".starts_with("-"));
+ assert!("ödd".starts_with("öd"));
+}
+
+#[test]
+fn test_ends_with() {
+ assert!("".ends_with(""));
+ assert!("abc".ends_with(""));
+ assert!("abc".ends_with("c"));
+ assert!(!"a".ends_with("abc"));
+ assert!(!"".ends_with("abc"));
+ assert!(!"ddö".ends_with("-"));
+ assert!("ddö".ends_with("dö"));
+}
+
+#[test]
+fn test_is_empty() {
+ assert!("".is_empty());
+ assert!(!"a".is_empty());
+}
+
+#[test]
+fn test_replacen() {
+ assert_eq!("".replacen('a', "b", 5), "");
+ assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
+ assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
+
+ let test = "test";
+ assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
+ assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
+ assert_eq!(" test test ".replacen(test, "", 5), " ");
+
+ assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
+}
+
+#[test]
+fn test_replace() {
+ let a = "a";
+ assert_eq!("".replace(a, "b"), "");
+ assert_eq!("a".replace(a, "b"), "b");
+ assert_eq!("ab".replace(a, "b"), "bb");
+ let test = "test";
+ assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
+ assert_eq!(" test test ".replace(test, ""), " ");
+}
+
+#[test]
+fn test_replace_2a() {
+ let data = "ประเทศไทย中华";
+ let repl = "دولة الكويت";
+
+ let a = "ประเ";
+ let a2 = "دولة الكويتทศไทย中华";
+ assert_eq!(data.replace(a, repl), a2);
+}
+
+#[test]
+fn test_replace_2b() {
+ let data = "ประเทศไทย中华";
+ let repl = "دولة الكويت";
+
+ let b = "ะเ";
+ let b2 = "ปรدولة الكويتทศไทย中华";
+ assert_eq!(data.replace(b, repl), b2);
+}
+
+#[test]
+fn test_replace_2c() {
+ let data = "ประเทศไทย中华";
+ let repl = "دولة الكويت";
+
+ let c = "中华";
+ let c2 = "ประเทศไทยدولة الكويت";
+ assert_eq!(data.replace(c, repl), c2);
+}
+
+#[test]
+fn test_replace_2d() {
+ let data = "ประเทศไทย中华";
+ let repl = "دولة الكويت";
+
+ let d = "ไท华";
+ assert_eq!(data.replace(d, repl), data);
+}
+
+#[test]
+fn test_replace_pattern() {
+ let data = "abcdαβγδabcdαβγδ";
+ assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
+ assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
+ assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
+ assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
+}
+
+#[test]
+fn test_slice() {
+ assert_eq!("ab", &"abc"[0..2]);
+ assert_eq!("bc", &"abc"[1..3]);
+ assert_eq!("", &"abc"[1..1]);
+ assert_eq!("\u{65e5}", &"\u{65e5}\u{672c}"[0..3]);
+
+ let data = "ประเทศไทย中华";
+ assert_eq!("ป", &data[0..3]);
+ assert_eq!("ร", &data[3..6]);
+ assert_eq!("", &data[3..3]);
+ assert_eq!("华", &data[30..33]);
+
+ fn a_million_letter_x() -> String {
+ let mut i = 0;
+ let mut rs = String::new();
+ while i < 100000 {
+ rs.push_str("华华华华华华华华华华");
+ i += 1;
+ }
+ rs
+ }
+ fn half_a_million_letter_x() -> String {
+ let mut i = 0;
+ let mut rs = String::new();
+ while i < 100000 {
+ rs.push_str("华华华华华");
+ i += 1;
+ }
+ rs
+ }
+ let letters = a_million_letter_x();
+ assert_eq!(half_a_million_letter_x(), &letters[0..3 * 500000]);
+}
+
+#[test]
+fn test_slice_2() {
+ let ss = "中华Việt Nam";
+
+ assert_eq!("华", &ss[3..6]);
+ assert_eq!("Việt Nam", &ss[6..16]);
+
+ assert_eq!("ab", &"abc"[0..2]);
+ assert_eq!("bc", &"abc"[1..3]);
+ assert_eq!("", &"abc"[1..1]);
+
+ assert_eq!("中", &ss[0..3]);
+ assert_eq!("华V", &ss[3..7]);
+ assert_eq!("", &ss[3..3]);
+ /*0: 中
+ 3: 华
+ 6: V
+ 7: i
+ 8: ệ
+ 11: t
+ 12:
+ 13: N
+ 14: a
+ 15: m */
+}
+
+#[test]
+#[should_panic]
+fn test_slice_fail() {
+ &"中华Việt Nam"[0..2];
+}
+
+
+#[test]
+fn test_is_char_boundary() {
+ let s = "ศไทย中华Việt Nam β-release 🐱123";
+ assert!(s.is_char_boundary(0));
+ assert!(s.is_char_boundary(s.len()));
+ assert!(!s.is_char_boundary(s.len() + 1));
+ for (i, ch) in s.char_indices() {
+ // ensure character locations are boundaries and continuation bytes are not
+ assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
+ for j in 1..ch.len_utf8() {
+ assert!(!s.is_char_boundary(i + j),
+ "{} should not be a char boundary in {:?}", i + j, s);
+ }
+ }
+}
+const LOREM_PARAGRAPH: &'static str = "\
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
+ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
+eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
+sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
+tempus vel, gravida nec quam.";
+
+// check the panic includes the prefix of the sliced string
+#[test]
+#[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
+fn test_slice_fail_truncated_1() {
+ &LOREM_PARAGRAPH[..1024];
+}
+// check the truncation in the panic message
+#[test]
+#[should_panic(expected="luctus, im`[...]")]
+fn test_slice_fail_truncated_2() {
+ &LOREM_PARAGRAPH[..1024];
+}
+
+#[test]
+#[should_panic(expected="byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of")]
+fn test_slice_fail_boundary_1() {
+ &"abcαβγ"[4..];
+}
+
+#[test]
+#[should_panic(expected="byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of")]
+fn test_slice_fail_boundary_2() {
+ &"abcαβγ"[2..6];
+}
+
+#[test]
+fn test_slice_from() {
+ assert_eq!(&"abcd"[0..], "abcd");
+ assert_eq!(&"abcd"[2..], "cd");
+ assert_eq!(&"abcd"[4..], "");
+}
+#[test]
+fn test_slice_to() {
+ assert_eq!(&"abcd"[..0], "");
+ assert_eq!(&"abcd"[..2], "ab");
+ assert_eq!(&"abcd"[..4], "abcd");
+}
+
+#[test]
+fn test_trim_left_matches() {
+ let v: &[char] = &[];
+ assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** ");
+ let chars: &[char] = &['*', ' '];
+ assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** ");
+ assert_eq!(" *** *** ".trim_left_matches(chars), "");
+ assert_eq!("foo *** ".trim_left_matches(chars), "foo *** ");
+
+ assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
+ let chars: &[char] = &['1', '2'];
+ assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12");
+ assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123");
+}
+
+#[test]
+fn test_trim_right_matches() {
+ let v: &[char] = &[];
+ assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** ");
+ let chars: &[char] = &['*', ' '];
+ assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo");
+ assert_eq!(" *** *** ".trim_right_matches(chars), "");
+ assert_eq!(" *** foo".trim_right_matches(chars), " *** foo");
+
+ assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
+ let chars: &[char] = &['1', '2'];
+ assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar");
+ assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar");
+}
+
+#[test]
+fn test_trim_matches() {
+ let v: &[char] = &[];
+ assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
+ let chars: &[char] = &['*', ' '];
+ assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
+ assert_eq!(" *** *** ".trim_matches(chars), "");
+ assert_eq!("foo".trim_matches(chars), "foo");
+
+ assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
+ let chars: &[char] = &['1', '2'];
+ assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
+ assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
+}
+
+#[test]
+fn test_trim_left() {
+ assert_eq!("".trim_left(), "");
+ assert_eq!("a".trim_left(), "a");
+ assert_eq!(" ".trim_left(), "");
+ assert_eq!(" blah".trim_left(), "blah");
+ assert_eq!(" \u{3000} wut".trim_left(), "wut");
+ assert_eq!("hey ".trim_left(), "hey ");
+}
+
+#[test]
+fn test_trim_right() {
+ assert_eq!("".trim_right(), "");
+ assert_eq!("a".trim_right(), "a");
+ assert_eq!(" ".trim_right(), "");
+ assert_eq!("blah ".trim_right(), "blah");
+ assert_eq!("wut \u{3000} ".trim_right(), "wut");
+ assert_eq!(" hey".trim_right(), " hey");
+}
+
+#[test]
+fn test_trim() {
+ assert_eq!("".trim(), "");
+ assert_eq!("a".trim(), "a");
+ assert_eq!(" ".trim(), "");
+ assert_eq!(" blah ".trim(), "blah");
+ assert_eq!("\nwut \u{3000} ".trim(), "wut");
+ assert_eq!(" hey dude ".trim(), "hey dude");
+}
+
+#[test]
+fn test_is_whitespace() {
+ assert!("".chars().all(|c| c.is_whitespace()));
+ assert!(" ".chars().all(|c| c.is_whitespace()));
+ assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
+ assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
+ assert!(!" _ ".chars().all(|c| c.is_whitespace()));
+}
+
+#[test]
+fn test_is_utf8() {
+ // deny overlong encodings
+ assert!(from_utf8(&[0xc0, 0x80]).is_err());
+ assert!(from_utf8(&[0xc0, 0xae]).is_err());
+ assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
+ assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
+ assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
+ assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
+ assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
+
+ // deny surrogates
+ assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
+ assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
+
+ assert!(from_utf8(&[0xC2, 0x80]).is_ok());
+ assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
+ assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
+ assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
+ assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
+ assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
+ assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
+ assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
+}
+
+#[test]
+fn from_utf8_mostly_ascii() {
+ // deny invalid bytes embedded in long stretches of ascii
+ for i in 32..64 {
+ let mut data = [0; 128];
+ data[i] = 0xC0;
+ assert!(from_utf8(&data).is_err());
+ data[i] = 0xC2;
+ assert!(from_utf8(&data).is_err());
+ }
+}
+
+#[test]
+fn from_utf8_error() {
+ macro_rules! test {
+ ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
+ let error = from_utf8($input).unwrap_err();
+ assert_eq!(error.valid_up_to(), $expected_valid_up_to);
+ assert_eq!(error.error_len(), $expected_error_len);
+ }
+ }
+ test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
+ test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
+ test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
+ test!(b"A\xC3\xA9 \xC1", 4, Some(1));
+ test!(b"A\xC3\xA9 \xC2", 4, None);
+ test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
+ test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
+ test!(b"A\xC3\xA9 \xE0", 4, None);
+ test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
+ test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
+ test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
+ test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
+ test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
+ test!(b"A\xC3\xA9 \xF1", 4, None);
+ test!(b"A\xC3\xA9 \xF1\x80", 4, None);
+ test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
+ test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
+ test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
+ test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
+}
+
+#[test]
+fn test_as_bytes() {
+ // no null
+ let v = [
+ 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
+ 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
+ 109
+ ];
+ let b: &[u8] = &[];
+ assert_eq!("".as_bytes(), b);
+ assert_eq!("abc".as_bytes(), b"abc");
+ assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
+}
+
+#[test]
+#[should_panic]
+fn test_as_bytes_fail() {
+ // Don't double free. (I'm not sure if this exercises the
+ // original problem code path anymore.)
+ let s = String::from("");
+ let _bytes = s.as_bytes();
+ panic!();
+}
+
+#[test]
+fn test_as_ptr() {
+ let buf = "hello".as_ptr();
+ unsafe {
+ assert_eq!(*buf.offset(0), b'h');
+ assert_eq!(*buf.offset(1), b'e');
+ assert_eq!(*buf.offset(2), b'l');
+ assert_eq!(*buf.offset(3), b'l');
+ assert_eq!(*buf.offset(4), b'o');
+ }
+}
+
+#[test]
+fn vec_str_conversions() {
+ let s1: String = String::from("All mimsy were the borogoves");
+
+ let v: Vec<u8> = s1.as_bytes().to_vec();
+ let s2: String = String::from(from_utf8(&v).unwrap());
+ let mut i = 0;
+ let n1 = s1.len();
+ let n2 = v.len();
+ assert_eq!(n1, n2);
+ while i < n1 {
+ let a: u8 = s1.as_bytes()[i];
+ let b: u8 = s2.as_bytes()[i];
+ assert_eq!(a, b);
+ i += 1;
+ }
+}
+
+#[test]
+fn test_contains() {
+ assert!("abcde".contains("bcd"));
+ assert!("abcde".contains("abcd"));
+ assert!("abcde".contains("bcde"));
+ assert!("abcde".contains(""));
+ assert!("".contains(""));
+ assert!(!"abcde".contains("def"));
+ assert!(!"".contains("a"));
+
+ let data = "ประเทศไทย中华Việt Nam";
+ assert!(data.contains("ประเ"));
+ assert!(data.contains("ะเ"));
+ assert!(data.contains("中华"));
+ assert!(!data.contains("ไท华"));
+}
+
+#[test]
+fn test_contains_char() {
+ assert!("abc".contains('b'));
+ assert!("a".contains('a'));
+ assert!(!"abc".contains('d'));
+ assert!(!"".contains('a'));
+}
+
+#[test]
+fn test_split_at() {
+ let s = "ศไทย中华Việt Nam";
+ for (index, _) in s.char_indices() {
+ let (a, b) = s.split_at(index);
+ assert_eq!(&s[..a.len()], a);
+ assert_eq!(&s[a.len()..], b);
+ }
+ let (a, b) = s.split_at(s.len());
+ assert_eq!(a, s);
+ assert_eq!(b, "");
+}
+
+#[test]
+fn test_split_at_mut() {
+ use std::ascii::AsciiExt;
+ let mut s = "Hello World".to_string();
+ {
+ let (a, b) = s.split_at_mut(5);
+ a.make_ascii_uppercase();
+ b.make_ascii_lowercase();
+ }
+ assert_eq!(s, "HELLO world");
+}
+
+#[test]
+#[should_panic]
+fn test_split_at_boundscheck() {
+ let s = "ศไทย中华Việt Nam";
+ s.split_at(1);
+}
+
+#[test]
+fn test_escape_unicode() {
+ assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
+ assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
+ assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
+ assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
+ assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
+ assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
+ assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
+ assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
+ assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
+}
+
+#[test]
+fn test_escape_debug() {
+ assert_eq!("abc".escape_debug(), "abc");
+ assert_eq!("a c".escape_debug(), "a c");
+ assert_eq!("éèê".escape_debug(), "éèê");
+ assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
+ assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
+ assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
+ assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
+ assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
+ assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
+ assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
+}
+
+#[test]
+fn test_escape_default() {
+ assert_eq!("abc".escape_default(), "abc");
+ assert_eq!("a c".escape_default(), "a c");
+ assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
+ assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
+ assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
+ assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
+ assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
+ assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
+ assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
+ assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
+}
+
+#[test]
+fn test_total_ord() {
+ assert_eq!("1234".cmp("123"), Greater);
+ assert_eq!("123".cmp("1234"), Less);
+ assert_eq!("1234".cmp("1234"), Equal);
+ assert_eq!("12345555".cmp("123456"), Less);
+ assert_eq!("22".cmp("1234"), Greater);
+}
+
+#[test]
+fn test_iterator() {
+ let s = "ศไทย中华Việt Nam";
+ let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+
+ let mut pos = 0;
+ let it = s.chars();
+
+ for c in it {
+ assert_eq!(c, v[pos]);
+ pos += 1;
+ }
+ assert_eq!(pos, v.len());
+ assert_eq!(s.chars().count(), v.len());
+}
+
+#[test]
+fn test_rev_iterator() {
+ let s = "ศไทย中华Việt Nam";
+ let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
+
+ let mut pos = 0;
+ let it = s.chars().rev();
+
+ for c in it {
+ assert_eq!(c, v[pos]);
+ pos += 1;
+ }
+ assert_eq!(pos, v.len());
+}
+
+#[test]
+fn test_chars_decoding() {
+ let mut bytes = [0; 4];
+ for c in (0..0x110000).filter_map(::std::char::from_u32) {
+ let s = c.encode_utf8(&mut bytes);
+ if Some(c) != s.chars().next() {
+ panic!("character {:x}={} does not decode correctly", c as u32, c);
+ }
+ }
+}
+
+#[test]
+fn test_chars_rev_decoding() {
+ let mut bytes = [0; 4];
+ for c in (0..0x110000).filter_map(::std::char::from_u32) {
+ let s = c.encode_utf8(&mut bytes);
+ if Some(c) != s.chars().rev().next() {
+ panic!("character {:x}={} does not decode correctly", c as u32, c);
+ }
+ }
+}
+
+#[test]
+fn test_iterator_clone() {
+ let s = "ศไทย中华Việt Nam";
+ let mut it = s.chars();
+ it.next();
+ assert!(it.clone().zip(it).all(|(x,y)| x == y));
+}
+
+#[test]
+fn test_iterator_last() {
+ let s = "ศไทย中华Việt Nam";
+ let mut it = s.chars();
+ it.next();
+ assert_eq!(it.last(), Some('m'));
+}
+
+#[test]
+fn test_bytesator() {
+ let s = "ศไทย中华Việt Nam";
+ let v = [
+ 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
+ 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
+ 109
+ ];
+ let mut pos = 0;
+
+ for b in s.bytes() {
+ assert_eq!(b, v[pos]);
+ pos += 1;
+ }
+}
+
+#[test]
+fn test_bytes_revator() {
+ let s = "ศไทย中华Việt Nam";
+ let v = [
+ 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
+ 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
+ 109
+ ];
+ let mut pos = v.len();
+
+ for b in s.bytes().rev() {
+ pos -= 1;
+ assert_eq!(b, v[pos]);
+ }
+}
+
+#[test]
+fn test_bytesator_nth() {
+ let s = "ศไทย中华Việt Nam";
+ let v = [
+ 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
+ 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
+ 109
+ ];
+
+ let mut b = s.bytes();
+ assert_eq!(b.nth(2).unwrap(), v[2]);
+ assert_eq!(b.nth(10).unwrap(), v[10]);
+ assert_eq!(b.nth(200), None);
+}
+
+#[test]
+fn test_bytesator_count() {
+ let s = "ศไทย中华Việt Nam";
+
+ let b = s.bytes();
+ assert_eq!(b.count(), 28)
+}
+
+#[test]
+fn test_bytesator_last() {
+ let s = "ศไทย中华Việt Nam";
+
+ let b = s.bytes();
+ assert_eq!(b.last().unwrap(), 109)
+}
+
+#[test]
+fn test_char_indicesator() {
+ let s = "ศไทย中华Việt Nam";
+ let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
+ let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+
+ let mut pos = 0;
+ let it = s.char_indices();
+
+ for c in it {
+ assert_eq!(c, (p[pos], v[pos]));
+ pos += 1;
+ }
+ assert_eq!(pos, v.len());
+ assert_eq!(pos, p.len());
+}
+
+#[test]
+fn test_char_indices_revator() {
+ let s = "ศไทย中华Việt Nam";
+ let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
+ let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
+
+ let mut pos = 0;
+ let it = s.char_indices().rev();
+
+ for c in it {
+ assert_eq!(c, (p[pos], v[pos]));
+ pos += 1;
+ }
+ assert_eq!(pos, v.len());
+ assert_eq!(pos, p.len());
+}
+
+#[test]
+fn test_char_indices_last() {
+ let s = "ศไทย中华Việt Nam";
+ let mut it = s.char_indices();
+ it.next();
+ assert_eq!(it.last(), Some((27, 'm')));
+}
+
+#[test]
+fn test_splitn_char_iterator() {
+ let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+ let split: Vec<&str> = data.splitn(4, ' ').collect();
+ assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
+
+ let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
+ assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
+
+ // Unicode
+ let split: Vec<&str> = data.splitn(4, 'ä').collect();
+ assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
+
+ let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
+ assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
+}
+
+#[test]
+fn test_split_char_iterator_no_trailing() {
+ let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+ let split: Vec<&str> = data.split('\n').collect();
+ assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
+
+ let split: Vec<&str> = data.split_terminator('\n').collect();
+ assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
+}
+
+#[test]
+fn test_rsplit() {
+ let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+ let split: Vec<&str> = data.rsplit(' ').collect();
+ assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
+
+ let split: Vec<&str> = data.rsplit("lämb").collect();
+ assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
+
+ let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
+ assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
+}
+
+#[test]
+fn test_rsplitn() {
+ let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+ let split: Vec<&str> = data.rsplitn(2, ' ').collect();
+ assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
+
+ let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
+ assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
+
+ let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
+ assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
+}
+
+#[test]
+fn test_split_whitespace() {
+ let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
+ let words: Vec<&str> = data.split_whitespace().collect();
+ assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
+}
+
+#[test]
+fn test_lines() {
+ let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
+ let lines: Vec<&str> = data.lines().collect();
+ assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
+
+ let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
+ let lines: Vec<&str> = data.lines().collect();
+ assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
+}
+
+#[test]
+fn test_splitator() {
+ fn t(s: &str, sep: &str, u: &[&str]) {
+ let v: Vec<&str> = s.split(sep).collect();
+ assert_eq!(v, u);
+ }
+ t("--1233345--", "12345", &["--1233345--"]);
+ t("abc::hello::there", "::", &["abc", "hello", "there"]);
+ t("::hello::there", "::", &["", "hello", "there"]);
+ t("hello::there::", "::", &["hello", "there", ""]);
+ t("::hello::there::", "::", &["", "hello", "there", ""]);
+ t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
+ t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
+ t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
+ t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
+ t("", ".", &[""]);
+ t("zz", "zz", &["",""]);
+ t("ok", "z", &["ok"]);
+ t("zzz", "zz", &["","z"]);
+ t("zzzzz", "zz", &["","","z"]);
+}
+
+#[test]
+fn test_str_default() {
+ use std::default::Default;
+
+ fn t<S: Default + AsRef<str>>() {
+ let s: S = Default::default();
+ assert_eq!(s.as_ref(), "");
+ }
+
+ t::<&str>();
+ t::<String>();
+}
+
+#[test]
+fn test_str_container() {
+ fn sum_len(v: &[&str]) -> usize {
+ v.iter().map(|x| x.len()).sum()
+ }
+
+ let s = "01234";
+ assert_eq!(5, sum_len(&["012", "", "34"]));
+ assert_eq!(5, sum_len(&["01", "2", "34", ""]));
+ assert_eq!(5, sum_len(&[s]));
+}
+
+#[test]
+fn test_str_from_utf8() {
+ let xs = b"hello";
+ assert_eq!(from_utf8(xs), Ok("hello"));
+
+ let xs = "ศไทย中华Việt Nam".as_bytes();
+ assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
+
+ let xs = b"hello\xFF";
+ assert!(from_utf8(xs).is_err());
+}
+
+#[test]
+fn test_pattern_deref_forward() {
+ let data = "aabcdaa";
+ assert!(data.contains("bcd"));
+ assert!(data.contains(&"bcd"));
+ assert!(data.contains(&"bcd".to_string()));
+}
+
+#[test]
+fn test_empty_match_indices() {
+ let data = "aä中!";
+ let vec: Vec<_> = data.match_indices("").collect();
+ assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
+}
+
+#[test]
+fn test_bool_from_str() {
+ assert_eq!("true".parse().ok(), Some(true));
+ assert_eq!("false".parse().ok(), Some(false));
+ assert_eq!("not even a boolean".parse::<bool>().ok(), None);
+}
+
+fn check_contains_all_substrings(s: &str) {
+ assert!(s.contains(""));
+ for i in 0..s.len() {
+ for j in i+1..s.len() + 1 {
+ assert!(s.contains(&s[i..j]));
+ }
+ }
+}
+
+#[test]
+fn strslice_issue_16589() {
+ assert!("bananas".contains("nana"));
+
+ // prior to the fix for #16589, x.contains("abcdabcd") returned false
+ // test all substrings for good measure
+ check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
+}
+
+#[test]
+fn strslice_issue_16878() {
+ assert!(!"1234567ah012345678901ah".contains("hah"));
+ assert!(!"00abc01234567890123456789abc".contains("bcabc"));
+}
+
+
+#[test]
+fn test_strslice_contains() {
+ let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
+ check_contains_all_substrings(x);
+}
+
+#[test]
+fn test_rsplitn_char_iterator() {
+ let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+ let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
+ split.reverse();
+ assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
+ split.reverse();
+ assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ // Unicode
+ let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
+ split.reverse();
+ assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
+
+ let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
+ split.reverse();
+ assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
+}
+
+#[test]
+fn test_split_char_iterator() {
+ let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+ let split: Vec<&str> = data.split(' ').collect();
+ assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
+ rsplit.reverse();
+ assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
+ assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
+ rsplit.reverse();
+ assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+
+ // Unicode
+ let split: Vec<&str> = data.split('ä').collect();
+ assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+
+ let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
+ rsplit.reverse();
+ assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+
+ let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
+ assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+
+ let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
+ rsplit.reverse();
+ assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+}
+
+#[test]
+fn test_rev_split_char_iterator_no_trailing() {
+ let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+ let mut split: Vec<&str> = data.split('\n').rev().collect();
+ split.reverse();
+ assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
+
+ let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
+ split.reverse();
+ assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
+}
+
+#[test]
+fn test_utf16_code_units() {
+ use std_unicode::str::Utf16Encoder;
+ assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
+ [0xE9, 0xD83D, 0xDCA9])
+}
+
+#[test]
+fn starts_with_in_unicode() {
+ assert!(!"├── Cargo.toml".starts_with("# "));
+}
+
+#[test]
+fn starts_short_long() {
+ assert!(!"".starts_with("##"));
+ assert!(!"##".starts_with("####"));
+ assert!("####".starts_with("##"));
+ assert!(!"##ä".starts_with("####"));
+ assert!("####ä".starts_with("##"));
+ assert!(!"##".starts_with("####ä"));
+ assert!("##ä##".starts_with("##ä"));
+
+ assert!("".starts_with(""));
+ assert!("ä".starts_with(""));
+ assert!("#ä".starts_with(""));
+ assert!("##ä".starts_with(""));
+ assert!("ä###".starts_with(""));
+ assert!("#ä##".starts_with(""));
+ assert!("##ä#".starts_with(""));
+}
+
+#[test]
+fn contains_weird_cases() {
+ assert!("* \t".contains(' '));
+ assert!(!"* \t".contains('?'));
+ assert!(!"* \t".contains('\u{1F4A9}'));
+}
+
+#[test]
+fn trim_ws() {
+ assert_eq!(" \t a \t ".trim_left_matches(|c: char| c.is_whitespace()),
+ "a \t ");
+ assert_eq!(" \t a \t ".trim_right_matches(|c: char| c.is_whitespace()),
+ " \t a");
+ assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
+ "a");
+ assert_eq!(" \t \t ".trim_left_matches(|c: char| c.is_whitespace()),
+ "");
+ assert_eq!(" \t \t ".trim_right_matches(|c: char| c.is_whitespace()),
+ "");
+ assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
+ "");
+}
+
+#[test]
+fn to_lowercase() {
+ assert_eq!("".to_lowercase(), "");
+ assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
+
+ // https://github.com/rust-lang/rust/issues/26035
+ assert_eq!("ΑΣ".to_lowercase(), "ας");
+ assert_eq!("Α'Σ".to_lowercase(), "α'ς");
+ assert_eq!("Α''Σ".to_lowercase(), "α''ς");
+
+ assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
+ assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
+ assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
+
+ assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
+ assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
+
+ assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
+ assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
+
+ assert_eq!("Α Σ".to_lowercase(), "α σ");
+ assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
+ assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
+
+ assert_eq!("Σ".to_lowercase(), "σ");
+ assert_eq!("'Σ".to_lowercase(), "'σ");
+ assert_eq!("''Σ".to_lowercase(), "''σ");
+
+ assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
+ assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
+ assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
+}
+
+#[test]
+fn to_uppercase() {
+ assert_eq!("".to_uppercase(), "");
+ assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
+}
+
+#[test]
+fn test_into_string() {
+ // The only way to acquire a Box<str> in the first place is through a String, so just
+ // test that we can round-trip between Box<str> and String.
+ let string = String::from("Some text goes here");
+ assert_eq!(string.clone().into_boxed_str().into_string(), string);
+}
+
+#[test]
+fn test_box_slice_clone() {
+ let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
+ let data2 = data.clone().into_boxed_str().clone().into_string();
+
+ assert_eq!(data, data2);
+}
+
+#[test]
+fn test_cow_from() {
+ let borrowed = "borrowed";
+ let owned = String::from("owned");
+ match (Cow::from(owned.clone()), Cow::from(borrowed)) {
+ (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
+ _ => panic!("invalid `Cow::from`"),
+ }
+}
+
+#[test]
+fn test_repeat() {
+ assert_eq!("".repeat(3), "");
+ assert_eq!("abc".repeat(0), "");
+ assert_eq!("α".repeat(3), "ααα");
+}
+
+mod pattern {
+ use std::str::pattern::Pattern;
+ use std::str::pattern::{Searcher, ReverseSearcher};
+ use std::str::pattern::SearchStep::{self, Match, Reject, Done};
+
+ macro_rules! make_test {
+ ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
+ #[allow(unused_imports)]
+ mod $name {
+ use std::str::pattern::SearchStep::{Match, Reject};
+ use super::{cmp_search_to_vec};
+ #[test]
+ fn fwd() {
+ cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
+ }
+ #[test]
+ fn bwd() {
+ cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
+ }
+ }
+ }
+ }
+
+ fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
+ right: Vec<SearchStep>)
+ where P::Searcher: ReverseSearcher<'a>
+ {
+ let mut searcher = pat.into_searcher(haystack);
+ let mut v = vec![];
+ loop {
+ match if !rev {searcher.next()} else {searcher.next_back()} {
+ Match(a, b) => v.push(Match(a, b)),
+ Reject(a, b) => v.push(Reject(a, b)),
+ Done => break,
+ }
+ }
+ if rev {
+ v.reverse();
+ }
+
+ let mut first_index = 0;
+ let mut err = None;
+
+ for (i, e) in right.iter().enumerate() {
+ match *e {
+ Match(a, b) | Reject(a, b)
+ if a <= b && a == first_index => {
+ first_index = b;
+ }
+ _ => {
+ err = Some(i);
+ break;
+ }
+ }
+ }
+
+ if let Some(err) = err {
+ panic!("Input skipped range at {}", err);
+ }
+
+ if first_index != haystack.len() {
+ panic!("Did not cover whole input");
+ }
+
+ assert_eq!(v, right);
+ }
+
+ make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
+ Reject(0, 1),
+ Match (1, 3),
+ Reject(3, 4),
+ Match (4, 6),
+ Reject(6, 7),
+ ]);
+ make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
+ Reject(0, 1),
+ Match (1, 3),
+ Reject(3, 4),
+ Match (4, 6),
+ Match (6, 8),
+ Reject(8, 9),
+ ]);
+ make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
+ Match (0, 0),
+ Reject(0, 1),
+ Match (1, 1),
+ Reject(1, 2),
+ Match (2, 2),
+ Reject(2, 3),
+ Match (3, 3),
+ Reject(3, 4),
+ Match (4, 4),
+ Reject(4, 5),
+ Match (5, 5),
+ Reject(5, 6),
+ Match (6, 6),
+ Reject(6, 7),
+ Match (7, 7),
+ ]);
+ make_test!(str_searcher_mulibyte_haystack, " ", "├──", [
+ Reject(0, 3),
+ Reject(3, 6),
+ Reject(6, 9),
+ ]);
+ make_test!(str_searcher_empty_needle_mulibyte_haystack, "", "├──", [
+ Match (0, 0),
+ Reject(0, 3),
+ Match (3, 3),
+ Reject(3, 6),
+ Match (6, 6),
+ Reject(6, 9),
+ Match (9, 9),
+ ]);
+ make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
+ Match(0, 0),
+ ]);
+ make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
+ ]);
+ make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
+ Reject(0, 1),
+ Match (1, 2),
+ Match (2, 3),
+ Reject(3, 4),
+ Match (4, 5),
+ Match (5, 6),
+ Reject(6, 7),
+ ]);
+ make_test!(char_searcher_mulibyte_haystack, ' ', "├──", [
+ Reject(0, 3),
+ Reject(3, 6),
+ Reject(6, 9),
+ ]);
+ make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
+ Reject(0, 1),
+ Reject(1, 2),
+ Reject(2, 3),
+ ]);
+
+}
+
+macro_rules! generate_iterator_test {
+ {
+ $name:ident {
+ $(
+ ($($arg:expr),*) -> [$($t:tt)*];
+ )*
+ }
+ with $fwd:expr, $bwd:expr;
+ } => {
+ #[test]
+ fn $name() {
+ $(
+ {
+ let res = vec![$($t)*];
+
+ let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
+ assert_eq!(fwd_vec, res);
+
+ let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
+ bwd_vec.reverse();
+ assert_eq!(bwd_vec, res);
+ }
+ )*
+ }
+ };
+ {
+ $name:ident {
+ $(
+ ($($arg:expr),*) -> [$($t:tt)*];
+ )*
+ }
+ with $fwd:expr;
+ } => {
+ #[test]
+ fn $name() {
+ $(
+ {
+ let res = vec![$($t)*];
+
+ let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
+ assert_eq!(fwd_vec, res);
+ }
+ )*
+ }
+ }
+}
+
+generate_iterator_test! {
+ double_ended_split {
+ ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
+ ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
+ }
+ with str::split, str::rsplit;
+}
+
+generate_iterator_test! {
+ double_ended_split_terminator {
+ ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
+ }
+ with str::split_terminator, str::rsplit_terminator;
+}
+
+generate_iterator_test! {
+ double_ended_matches {
+ ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
+ }
+ with str::matches, str::rmatches;
+}
+
+generate_iterator_test! {
+ double_ended_match_indices {
+ ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
+ }
+ with str::match_indices, str::rmatch_indices;
+}
+
+generate_iterator_test! {
+ not_double_ended_splitn {
+ ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
+ }
+ with str::splitn;
+}
+
+generate_iterator_test! {
+ not_double_ended_rsplitn {
+ ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
+ }
+ with str::rsplitn;
+}
+
+#[test]
+fn different_str_pattern_forwarding_lifetimes() {
+ use std::str::pattern::Pattern;
+
+ fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
+ for _ in 0..3 {
+ "asdf".find(&p);
+ }
+ }
+
+ foo::<&str>("x");
+}
--- /dev/null
+// Copyright 2014 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.
+
+use std::borrow::Cow;
+
+pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
+ fn into_cow(self) -> Cow<'a, B>;
+}
+
+impl<'a> IntoCow<'a, str> for String {
+ fn into_cow(self) -> Cow<'a, str> {
+ Cow::Owned(self)
+ }
+}
+
+impl<'a> IntoCow<'a, str> for &'a str {
+ fn into_cow(self) -> Cow<'a, str> {
+ Cow::Borrowed(self)
+ }
+}
+
+#[test]
+fn test_from_str() {
+ let owned: Option<::std::string::String> = "string".parse().ok();
+ assert_eq!(owned.as_ref().map(|s| &**s), Some("string"));
+}
+
+#[test]
+fn test_from_cow_str() {
+ assert_eq!(String::from(Cow::Borrowed("string")), "string");
+ assert_eq!(String::from(Cow::Owned(String::from("string"))), "string");
+}
+
+#[test]
+fn test_unsized_to_string() {
+ let s: &str = "abc";
+ let _: String = (*s).to_string();
+}
+
+#[test]
+fn test_from_utf8() {
+ let xs = b"hello".to_vec();
+ assert_eq!(String::from_utf8(xs).unwrap(), String::from("hello"));
+
+ let xs = "ศไทย中华Việt Nam".as_bytes().to_vec();
+ assert_eq!(String::from_utf8(xs).unwrap(),
+ String::from("ศไทย中华Việt Nam"));
+
+ let xs = b"hello\xFF".to_vec();
+ let err = String::from_utf8(xs).unwrap_err();
+ assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
+}
+
+#[test]
+fn test_from_utf8_lossy() {
+ let xs = b"hello";
+ let ys: Cow<str> = "hello".into_cow();
+ assert_eq!(String::from_utf8_lossy(xs), ys);
+
+ let xs = "ศไทย中华Việt Nam".as_bytes();
+ let ys: Cow<str> = "ศไทย中华Việt Nam".into_cow();
+ assert_eq!(String::from_utf8_lossy(xs), ys);
+
+ let xs = b"Hello\xC2 There\xFF Goodbye";
+ assert_eq!(String::from_utf8_lossy(xs),
+ String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow());
+
+ let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
+ assert_eq!(String::from_utf8_lossy(xs),
+ String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow());
+
+ let xs = b"\xF5foo\xF5\x80bar";
+ assert_eq!(String::from_utf8_lossy(xs),
+ String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow());
+
+ let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
+ assert_eq!(String::from_utf8_lossy(xs),
+ String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow());
+
+ let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
+ assert_eq!(String::from_utf8_lossy(xs),
+ String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow());
+
+ let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
+ assert_eq!(String::from_utf8_lossy(xs),
+ String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar").into_cow());
+
+ // surrogates
+ let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
+ assert_eq!(String::from_utf8_lossy(xs),
+ String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow());
+}
+
+#[test]
+fn test_from_utf16() {
+ let pairs = [(String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
+ vec![0xd800, 0xdf45, 0xd800, 0xdf3f, 0xd800, 0xdf3b, 0xd800, 0xdf46, 0xd800,
+ 0xdf39, 0xd800, 0xdf3b, 0xd800, 0xdf30, 0x000a]),
+
+ (String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
+ vec![0xd801, 0xdc12, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc40, 0xd801,
+ 0xdc32, 0xd801, 0xdc4b, 0x0020, 0xd801, 0xdc0f, 0xd801, 0xdc32, 0xd801,
+ 0xdc4d, 0x000a]),
+
+ (String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
+ vec![0xd800, 0xdf00, 0xd800, 0xdf16, 0xd800, 0xdf0b, 0xd800, 0xdf04, 0xd800,
+ 0xdf11, 0xd800, 0xdf09, 0x00b7, 0xd800, 0xdf0c, 0xd800, 0xdf04, 0xd800,
+ 0xdf15, 0xd800, 0xdf04, 0xd800, 0xdf0b, 0xd800, 0xdf09, 0xd800, 0xdf11,
+ 0x000a]),
+
+ (String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
+ vec![0xd801, 0xdc8b, 0xd801, 0xdc98, 0xd801, 0xdc88, 0xd801, 0xdc91, 0xd801,
+ 0xdc9b, 0xd801, 0xdc92, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc93, 0x0020,
+ 0xd801, 0xdc88, 0xd801, 0xdc9a, 0xd801, 0xdc8d, 0x0020, 0xd801, 0xdc8f,
+ 0xd801, 0xdc9c, 0xd801, 0xdc92, 0xd801, 0xdc96, 0xd801, 0xdc86, 0x0020,
+ 0xd801, 0xdc95, 0xd801, 0xdc86, 0x000a]),
+ // Issue #12318, even-numbered non-BMP planes
+ (String::from("\u{20000}"), vec![0xD840, 0xDC00])];
+
+ for p in &pairs {
+ let (s, u) = (*p).clone();
+ let s_as_utf16 = s.encode_utf16().collect::<Vec<u16>>();
+ let u_as_string = String::from_utf16(&u).unwrap();
+
+ assert!(::std_unicode::char::decode_utf16(u.iter().cloned()).all(|r| r.is_ok()));
+ assert_eq!(s_as_utf16, u);
+
+ assert_eq!(u_as_string, s);
+ assert_eq!(String::from_utf16_lossy(&u), s);
+
+ assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s);
+ assert_eq!(u_as_string.encode_utf16().collect::<Vec<u16>>(), u);
+ }
+}
+
+#[test]
+fn test_utf16_invalid() {
+ // completely positive cases tested above.
+ // lead + eof
+ assert!(String::from_utf16(&[0xD800]).is_err());
+ // lead + lead
+ assert!(String::from_utf16(&[0xD800, 0xD800]).is_err());
+
+ // isolated trail
+ assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err());
+
+ // general
+ assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err());
+}
+
+#[test]
+fn test_from_utf16_lossy() {
+ // completely positive cases tested above.
+ // lead + eof
+ assert_eq!(String::from_utf16_lossy(&[0xD800]),
+ String::from("\u{FFFD}"));
+ // lead + lead
+ assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]),
+ String::from("\u{FFFD}\u{FFFD}"));
+
+ // isolated trail
+ assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]),
+ String::from("a\u{FFFD}"));
+
+ // general
+ assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]),
+ String::from("\u{FFFD}𐒋\u{FFFD}"));
+}
+
+#[test]
+fn test_push_bytes() {
+ let mut s = String::from("ABC");
+ unsafe {
+ let mv = s.as_mut_vec();
+ mv.extend_from_slice(&[b'D']);
+ }
+ assert_eq!(s, "ABCD");
+}
+
+#[test]
+fn test_push_str() {
+ let mut s = String::new();
+ s.push_str("");
+ assert_eq!(&s[0..], "");
+ s.push_str("abc");
+ assert_eq!(&s[0..], "abc");
+ s.push_str("ประเทศไทย中华Việt Nam");
+ assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam");
+}
+
+#[test]
+fn test_add_assign() {
+ let mut s = String::new();
+ s += "";
+ assert_eq!(s.as_str(), "");
+ s += "abc";
+ assert_eq!(s.as_str(), "abc");
+ s += "ประเทศไทย中华Việt Nam";
+ assert_eq!(s.as_str(), "abcประเทศไทย中华Việt Nam");
+}
+
+#[test]
+fn test_push() {
+ let mut data = String::from("ประเทศไทย中");
+ data.push('华');
+ data.push('b'); // 1 byte
+ data.push('¢'); // 2 byte
+ data.push('€'); // 3 byte
+ data.push('𤭢'); // 4 byte
+ assert_eq!(data, "ประเทศไทย中华b¢€𤭢");
+}
+
+#[test]
+fn test_pop() {
+ let mut data = String::from("ประเทศไทย中华b¢€𤭢");
+ assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes
+ assert_eq!(data.pop().unwrap(), '€'); // 3 bytes
+ assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes
+ assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes
+ assert_eq!(data.pop().unwrap(), '华');
+ assert_eq!(data, "ประเทศไทย中");
+}
+
+#[test]
+fn test_split_off_empty() {
+ let orig = "Hello, world!";
+ let mut split = String::from(orig);
+ let empty: String = split.split_off(orig.len());
+ assert!(empty.is_empty());
+}
+
+#[test]
+#[should_panic]
+fn test_split_off_past_end() {
+ let orig = "Hello, world!";
+ let mut split = String::from(orig);
+ split.split_off(orig.len() + 1);
+}
+
+#[test]
+#[should_panic]
+fn test_split_off_mid_char() {
+ let mut orig = String::from("山");
+ orig.split_off(1);
+}
+
+#[test]
+fn test_split_off_ascii() {
+ let mut ab = String::from("ABCD");
+ let cd = ab.split_off(2);
+ assert_eq!(ab, "AB");
+ assert_eq!(cd, "CD");
+}
+
+#[test]
+fn test_split_off_unicode() {
+ let mut nihon = String::from("日本語");
+ let go = nihon.split_off("日本".len());
+ assert_eq!(nihon, "日本");
+ assert_eq!(go, "語");
+}
+
+#[test]
+fn test_str_truncate() {
+ let mut s = String::from("12345");
+ s.truncate(5);
+ assert_eq!(s, "12345");
+ s.truncate(3);
+ assert_eq!(s, "123");
+ s.truncate(0);
+ assert_eq!(s, "");
+
+ let mut s = String::from("12345");
+ let p = s.as_ptr();
+ s.truncate(3);
+ s.push_str("6");
+ let p_ = s.as_ptr();
+ assert_eq!(p_, p);
+}
+
+#[test]
+fn test_str_truncate_invalid_len() {
+ let mut s = String::from("12345");
+ s.truncate(6);
+ assert_eq!(s, "12345");
+}
+
+#[test]
+#[should_panic]
+fn test_str_truncate_split_codepoint() {
+ let mut s = String::from("\u{FC}"); // ü
+ s.truncate(1);
+}
+
+#[test]
+fn test_str_clear() {
+ let mut s = String::from("12345");
+ s.clear();
+ assert_eq!(s.len(), 0);
+ assert_eq!(s, "");
+}
+
+#[test]
+fn test_str_add() {
+ let a = String::from("12345");
+ let b = a + "2";
+ let b = b + "2";
+ assert_eq!(b.len(), 7);
+ assert_eq!(b, "1234522");
+}
+
+#[test]
+fn remove() {
+ let mut s = "ศไทย中华Việt Nam; foobar".to_string();
+ assert_eq!(s.remove(0), 'ศ');
+ assert_eq!(s.len(), 33);
+ assert_eq!(s, "ไทย中华Việt Nam; foobar");
+ assert_eq!(s.remove(17), 'ệ');
+ assert_eq!(s, "ไทย中华Vit Nam; foobar");
+}
+
+#[test]
+#[should_panic]
+fn remove_bad() {
+ "ศ".to_string().remove(1);
+}
+
+#[test]
+fn insert() {
+ let mut s = "foobar".to_string();
+ s.insert(0, 'ệ');
+ assert_eq!(s, "ệfoobar");
+ s.insert(6, 'ย');
+ assert_eq!(s, "ệfooยbar");
+}
+
+#[test]
+#[should_panic]
+fn insert_bad1() {
+ "".to_string().insert(1, 't');
+}
+#[test]
+#[should_panic]
+fn insert_bad2() {
+ "ệ".to_string().insert(1, 't');
+}
+
+#[test]
+fn test_slicing() {
+ let s = "foobar".to_string();
+ assert_eq!("foobar", &s[..]);
+ assert_eq!("foo", &s[..3]);
+ assert_eq!("bar", &s[3..]);
+ assert_eq!("oob", &s[1..4]);
+}
+
+#[test]
+fn test_simple_types() {
+ assert_eq!(1.to_string(), "1");
+ assert_eq!((-1).to_string(), "-1");
+ assert_eq!(200.to_string(), "200");
+ assert_eq!(2.to_string(), "2");
+ assert_eq!(true.to_string(), "true");
+ assert_eq!(false.to_string(), "false");
+ assert_eq!(("hi".to_string()).to_string(), "hi");
+}
+
+#[test]
+fn test_vectors() {
+ let x: Vec<i32> = vec![];
+ assert_eq!(format!("{:?}", x), "[]");
+ assert_eq!(format!("{:?}", vec![1]), "[1]");
+ assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]");
+ assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == "[[], [1], [1, 1]]");
+}
+
+#[test]
+fn test_from_iterator() {
+ let s = "ศไทย中华Việt Nam".to_string();
+ let t = "ศไทย中华";
+ let u = "Việt Nam";
+
+ let a: String = s.chars().collect();
+ assert_eq!(s, a);
+
+ let mut b = t.to_string();
+ b.extend(u.chars());
+ assert_eq!(s, b);
+
+ let c: String = vec![t, u].into_iter().collect();
+ assert_eq!(s, c);
+
+ let mut d = t.to_string();
+ d.extend(vec![u]);
+ assert_eq!(s, d);
+}
+
+#[test]
+fn test_drain() {
+ let mut s = String::from("αβγ");
+ assert_eq!(s.drain(2..4).collect::<String>(), "β");
+ assert_eq!(s, "αγ");
+
+ let mut t = String::from("abcd");
+ t.drain(..0);
+ assert_eq!(t, "abcd");
+ t.drain(..1);
+ assert_eq!(t, "bcd");
+ t.drain(3..);
+ assert_eq!(t, "bcd");
+ t.drain(..);
+ assert_eq!(t, "");
+}
+
+#[test]
+fn test_extend_ref() {
+ let mut a = "foo".to_string();
+ a.extend(&['b', 'a', 'r']);
+
+ assert_eq!(&a, "foobar");
+}
+
+#[test]
+fn test_into_boxed_str() {
+ let xs = String::from("hello my name is bob");
+ let ys = xs.into_boxed_str();
+ assert_eq!(&*ys, "hello my name is bob");
+}
--- /dev/null
+// Copyright 2014 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.
+
+use std::ascii::AsciiExt;
+use std::borrow::Cow;
+use std::mem::size_of;
+use std::panic;
+use std::vec::{Drain, IntoIter};
+
+struct DropCounter<'a> {
+ count: &'a mut u32,
+}
+
+impl<'a> Drop for DropCounter<'a> {
+ fn drop(&mut self) {
+ *self.count += 1;
+ }
+}
+
+#[test]
+fn test_small_vec_struct() {
+ assert!(size_of::<Vec<u8>>() == size_of::<usize>() * 3);
+}
+
+#[test]
+fn test_double_drop() {
+ struct TwoVec<T> {
+ x: Vec<T>,
+ y: Vec<T>,
+ }
+
+ let (mut count_x, mut count_y) = (0, 0);
+ {
+ let mut tv = TwoVec {
+ x: Vec::new(),
+ y: Vec::new(),
+ };
+ tv.x.push(DropCounter { count: &mut count_x });
+ tv.y.push(DropCounter { count: &mut count_y });
+
+ // If Vec had a drop flag, here is where it would be zeroed.
+ // Instead, it should rely on its internal state to prevent
+ // doing anything significant when dropped multiple times.
+ drop(tv.x);
+
+ // Here tv goes out of scope, tv.y should be dropped, but not tv.x.
+ }
+
+ assert_eq!(count_x, 1);
+ assert_eq!(count_y, 1);
+}
+
+#[test]
+fn test_reserve() {
+ let mut v = Vec::new();
+ assert_eq!(v.capacity(), 0);
+
+ v.reserve(2);
+ assert!(v.capacity() >= 2);
+
+ for i in 0..16 {
+ v.push(i);
+ }
+
+ assert!(v.capacity() >= 16);
+ v.reserve(16);
+ assert!(v.capacity() >= 32);
+
+ v.push(16);
+
+ v.reserve(16);
+ assert!(v.capacity() >= 33)
+}
+
+#[test]
+fn test_extend() {
+ let mut v = Vec::new();
+ let mut w = Vec::new();
+
+ v.extend(0..3);
+ for i in 0..3 {
+ w.push(i)
+ }
+
+ assert_eq!(v, w);
+
+ v.extend(3..10);
+ for i in 3..10 {
+ w.push(i)
+ }
+
+ assert_eq!(v, w);
+
+ v.extend(w.clone()); // specializes to `append`
+ assert!(v.iter().eq(w.iter().chain(w.iter())));
+}
+
+#[test]
+fn test_extend_ref() {
+ let mut v = vec![1, 2];
+ v.extend(&[3, 4, 5]);
+
+ assert_eq!(v.len(), 5);
+ assert_eq!(v, [1, 2, 3, 4, 5]);
+
+ let w = vec![6, 7];
+ v.extend(&w);
+
+ assert_eq!(v.len(), 7);
+ assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);
+}
+
+#[test]
+fn test_slice_from_mut() {
+ let mut values = vec![1, 2, 3, 4, 5];
+ {
+ let slice = &mut values[2..];
+ assert!(slice == [3, 4, 5]);
+ for p in slice {
+ *p += 2;
+ }
+ }
+
+ assert!(values == [1, 2, 5, 6, 7]);
+}
+
+#[test]
+fn test_slice_to_mut() {
+ let mut values = vec![1, 2, 3, 4, 5];
+ {
+ let slice = &mut values[..2];
+ assert!(slice == [1, 2]);
+ for p in slice {
+ *p += 1;
+ }
+ }
+
+ assert!(values == [2, 3, 3, 4, 5]);
+}
+
+#[test]
+fn test_split_at_mut() {
+ let mut values = vec![1, 2, 3, 4, 5];
+ {
+ let (left, right) = values.split_at_mut(2);
+ {
+ let left: &[_] = left;
+ assert!(&left[..left.len()] == &[1, 2]);
+ }
+ for p in left {
+ *p += 1;
+ }
+
+ {
+ let right: &[_] = right;
+ assert!(&right[..right.len()] == &[3, 4, 5]);
+ }
+ for p in right {
+ *p += 2;
+ }
+ }
+
+ assert_eq!(values, [2, 3, 5, 6, 7]);
+}
+
+#[test]
+fn test_clone() {
+ let v: Vec<i32> = vec![];
+ let w = vec![1, 2, 3];
+
+ assert_eq!(v, v.clone());
+
+ let z = w.clone();
+ assert_eq!(w, z);
+ // they should be disjoint in memory.
+ assert!(w.as_ptr() != z.as_ptr())
+}
+
+#[test]
+fn test_clone_from() {
+ let mut v = vec![];
+ let three: Vec<Box<_>> = vec![box 1, box 2, box 3];
+ let two: Vec<Box<_>> = vec![box 4, box 5];
+ // zero, long
+ v.clone_from(&three);
+ assert_eq!(v, three);
+
+ // equal
+ v.clone_from(&three);
+ assert_eq!(v, three);
+
+ // long, short
+ v.clone_from(&two);
+ assert_eq!(v, two);
+
+ // short, long
+ v.clone_from(&three);
+ assert_eq!(v, three)
+}
+
+#[test]
+fn test_retain() {
+ let mut vec = vec![1, 2, 3, 4];
+ vec.retain(|&x| x % 2 == 0);
+ assert_eq!(vec, [2, 4]);
+}
+
+#[test]
+fn test_dedup() {
+ fn case(a: Vec<i32>, b: Vec<i32>) {
+ let mut v = a;
+ v.dedup();
+ assert_eq!(v, b);
+ }
+ case(vec![], vec![]);
+ case(vec![1], vec![1]);
+ case(vec![1, 1], vec![1]);
+ case(vec![1, 2, 3], vec![1, 2, 3]);
+ case(vec![1, 1, 2, 3], vec![1, 2, 3]);
+ case(vec![1, 2, 2, 3], vec![1, 2, 3]);
+ case(vec![1, 2, 3, 3], vec![1, 2, 3]);
+ case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
+}
+
+#[test]
+fn test_dedup_by_key() {
+ fn case(a: Vec<i32>, b: Vec<i32>) {
+ let mut v = a;
+ v.dedup_by_key(|i| *i / 10);
+ assert_eq!(v, b);
+ }
+ case(vec![], vec![]);
+ case(vec![10], vec![10]);
+ case(vec![10, 11], vec![10]);
+ case(vec![10, 20, 30], vec![10, 20, 30]);
+ case(vec![10, 11, 20, 30], vec![10, 20, 30]);
+ case(vec![10, 20, 21, 30], vec![10, 20, 30]);
+ case(vec![10, 20, 30, 31], vec![10, 20, 30]);
+ case(vec![10, 11, 20, 21, 22, 30, 31], vec![10, 20, 30]);
+}
+
+#[test]
+fn test_dedup_by() {
+ let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
+ vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
+
+ assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
+}
+
+#[test]
+fn test_dedup_unique() {
+ let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
+ v0.dedup();
+ let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
+ v1.dedup();
+ let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
+ v2.dedup();
+ // If the boxed pointers were leaked or otherwise misused, valgrind
+ // and/or rt should raise errors.
+}
+
+#[test]
+fn zero_sized_values() {
+ let mut v = Vec::new();
+ assert_eq!(v.len(), 0);
+ v.push(());
+ assert_eq!(v.len(), 1);
+ v.push(());
+ assert_eq!(v.len(), 2);
+ assert_eq!(v.pop(), Some(()));
+ assert_eq!(v.pop(), Some(()));
+ assert_eq!(v.pop(), None);
+
+ assert_eq!(v.iter().count(), 0);
+ v.push(());
+ assert_eq!(v.iter().count(), 1);
+ v.push(());
+ assert_eq!(v.iter().count(), 2);
+
+ for &() in &v {}
+
+ assert_eq!(v.iter_mut().count(), 2);
+ v.push(());
+ assert_eq!(v.iter_mut().count(), 3);
+ v.push(());
+ assert_eq!(v.iter_mut().count(), 4);
+
+ for &mut () in &mut v {}
+ unsafe {
+ v.set_len(0);
+ }
+ assert_eq!(v.iter_mut().count(), 0);
+}
+
+#[test]
+fn test_partition() {
+ assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3),
+ (vec![], vec![]));
+ assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4),
+ (vec![1, 2, 3], vec![]));
+ assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2),
+ (vec![1], vec![2, 3]));
+ assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0),
+ (vec![], vec![1, 2, 3]));
+}
+
+#[test]
+fn test_zip_unzip() {
+ let z1 = vec![(1, 4), (2, 5), (3, 6)];
+
+ let (left, right): (Vec<_>, Vec<_>) = z1.iter().cloned().unzip();
+
+ assert_eq!((1, 4), (left[0], right[0]));
+ assert_eq!((2, 5), (left[1], right[1]));
+ assert_eq!((3, 6), (left[2], right[2]));
+}
+
+#[test]
+fn test_vec_truncate_drop() {
+ static mut DROPS: u32 = 0;
+ struct Elem(i32);
+ impl Drop for Elem {
+ fn drop(&mut self) {
+ unsafe {
+ DROPS += 1;
+ }
+ }
+ }
+
+ let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
+ assert_eq!(unsafe { DROPS }, 0);
+ v.truncate(3);
+ assert_eq!(unsafe { DROPS }, 2);
+ v.truncate(0);
+ assert_eq!(unsafe { DROPS }, 5);
+}
+
+#[test]
+#[should_panic]
+fn test_vec_truncate_fail() {
+ struct BadElem(i32);
+ impl Drop for BadElem {
+ fn drop(&mut self) {
+ let BadElem(ref mut x) = *self;
+ if *x == 0xbadbeef {
+ panic!("BadElem panic: 0xbadbeef")
+ }
+ }
+ }
+
+ let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)];
+ v.truncate(0);
+}
+
+#[test]
+fn test_index() {
+ let vec = vec![1, 2, 3];
+ assert!(vec[1] == 2);
+}
+
+#[test]
+#[should_panic]
+fn test_index_out_of_bounds() {
+ let vec = vec![1, 2, 3];
+ let _ = vec[3];
+}
+
+#[test]
+#[should_panic]
+fn test_slice_out_of_bounds_1() {
+ let x = vec![1, 2, 3, 4, 5];
+ &x[!0..];
+}
+
+#[test]
+#[should_panic]
+fn test_slice_out_of_bounds_2() {
+ let x = vec![1, 2, 3, 4, 5];
+ &x[..6];
+}
+
+#[test]
+#[should_panic]
+fn test_slice_out_of_bounds_3() {
+ let x = vec![1, 2, 3, 4, 5];
+ &x[!0..4];
+}
+
+#[test]
+#[should_panic]
+fn test_slice_out_of_bounds_4() {
+ let x = vec![1, 2, 3, 4, 5];
+ &x[1..6];
+}
+
+#[test]
+#[should_panic]
+fn test_slice_out_of_bounds_5() {
+ let x = vec![1, 2, 3, 4, 5];
+ &x[3..2];
+}
+
+#[test]
+#[should_panic]
+fn test_swap_remove_empty() {
+ let mut vec = Vec::<i32>::new();
+ vec.swap_remove(0);
+}
+
+#[test]
+fn test_move_items() {
+ let vec = vec![1, 2, 3];
+ let mut vec2 = vec![];
+ for i in vec {
+ vec2.push(i);
+ }
+ assert_eq!(vec2, [1, 2, 3]);
+}
+
+#[test]
+fn test_move_items_reverse() {
+ let vec = vec![1, 2, 3];
+ let mut vec2 = vec![];
+ for i in vec.into_iter().rev() {
+ vec2.push(i);
+ }
+ assert_eq!(vec2, [3, 2, 1]);
+}
+
+#[test]
+fn test_move_items_zero_sized() {
+ let vec = vec![(), (), ()];
+ let mut vec2 = vec![];
+ for i in vec {
+ vec2.push(i);
+ }
+ assert_eq!(vec2, [(), (), ()]);
+}
+
+#[test]
+fn test_drain_items() {
+ let mut vec = vec![1, 2, 3];
+ let mut vec2 = vec![];
+ for i in vec.drain(..) {
+ vec2.push(i);
+ }
+ assert_eq!(vec, []);
+ assert_eq!(vec2, [1, 2, 3]);
+}
+
+#[test]
+fn test_drain_items_reverse() {
+ let mut vec = vec![1, 2, 3];
+ let mut vec2 = vec![];
+ for i in vec.drain(..).rev() {
+ vec2.push(i);
+ }
+ assert_eq!(vec, []);
+ assert_eq!(vec2, [3, 2, 1]);
+}
+
+#[test]
+fn test_drain_items_zero_sized() {
+ let mut vec = vec![(), (), ()];
+ let mut vec2 = vec![];
+ for i in vec.drain(..) {
+ vec2.push(i);
+ }
+ assert_eq!(vec, []);
+ assert_eq!(vec2, [(), (), ()]);
+}
+
+#[test]
+#[should_panic]
+fn test_drain_out_of_bounds() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ v.drain(5..6);
+}
+
+#[test]
+fn test_drain_range() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ for _ in v.drain(4..) {
+ }
+ assert_eq!(v, &[1, 2, 3, 4]);
+
+ let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect();
+ for _ in v.drain(1..4) {
+ }
+ assert_eq!(v, &[1.to_string(), 5.to_string()]);
+
+ let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect();
+ for _ in v.drain(1..4).rev() {
+ }
+ assert_eq!(v, &[1.to_string(), 5.to_string()]);
+
+ let mut v: Vec<_> = vec![(); 5];
+ for _ in v.drain(1..4).rev() {
+ }
+ assert_eq!(v, &[(), ()]);
+}
+
+#[test]
+fn test_drain_inclusive_range() {
+ let mut v = vec!['a', 'b', 'c', 'd', 'e'];
+ for _ in v.drain(1...3) {
+ }
+ assert_eq!(v, &['a', 'e']);
+
+ let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect();
+ for _ in v.drain(1...5) {
+ }
+ assert_eq!(v, &["0".to_string()]);
+
+ let mut v: Vec<String> = (0...5).map(|x| x.to_string()).collect();
+ for _ in v.drain(0...5) {
+ }
+ assert_eq!(v, Vec::<String>::new());
+
+ let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect();
+ for _ in v.drain(0...3) {
+ }
+ assert_eq!(v, &["4".to_string(), "5".to_string()]);
+
+ let mut v: Vec<_> = (0...1).map(|x| x.to_string()).collect();
+ for _ in v.drain(...0) {
+ }
+ assert_eq!(v, &["1".to_string()]);
+}
+
+#[test]
+fn test_drain_max_vec_size() {
+ let mut v = Vec::<()>::with_capacity(usize::max_value());
+ unsafe { v.set_len(usize::max_value()); }
+ for _ in v.drain(usize::max_value() - 1..) {
+ }
+ assert_eq!(v.len(), usize::max_value() - 1);
+
+ let mut v = Vec::<()>::with_capacity(usize::max_value());
+ unsafe { v.set_len(usize::max_value()); }
+ for _ in v.drain(usize::max_value() - 1...usize::max_value() - 1) {
+ }
+ assert_eq!(v.len(), usize::max_value() - 1);
+}
+
+#[test]
+#[should_panic]
+fn test_drain_inclusive_out_of_bounds() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ v.drain(5...5);
+}
+
+#[test]
+fn test_into_boxed_slice() {
+ let xs = vec![1, 2, 3];
+ let ys = xs.into_boxed_slice();
+ assert_eq!(&*ys, [1, 2, 3]);
+}
+
+#[test]
+fn test_append() {
+ let mut vec = vec![1, 2, 3];
+ let mut vec2 = vec![4, 5, 6];
+ vec.append(&mut vec2);
+ assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
+ assert_eq!(vec2, []);
+}
+
+#[test]
+fn test_split_off() {
+ let mut vec = vec![1, 2, 3, 4, 5, 6];
+ let vec2 = vec.split_off(4);
+ assert_eq!(vec, [1, 2, 3, 4]);
+ assert_eq!(vec2, [5, 6]);
+}
+
+#[test]
+fn test_into_iter_as_slice() {
+ let vec = vec!['a', 'b', 'c'];
+ let mut into_iter = vec.into_iter();
+ assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+ let _ = into_iter.next().unwrap();
+ assert_eq!(into_iter.as_slice(), &['b', 'c']);
+ let _ = into_iter.next().unwrap();
+ let _ = into_iter.next().unwrap();
+ assert_eq!(into_iter.as_slice(), &[]);
+}
+
+#[test]
+fn test_into_iter_as_mut_slice() {
+ let vec = vec!['a', 'b', 'c'];
+ let mut into_iter = vec.into_iter();
+ assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+ into_iter.as_mut_slice()[0] = 'x';
+ into_iter.as_mut_slice()[1] = 'y';
+ assert_eq!(into_iter.next().unwrap(), 'x');
+ assert_eq!(into_iter.as_slice(), &['y', 'c']);
+}
+
+#[test]
+fn test_into_iter_debug() {
+ let vec = vec!['a', 'b', 'c'];
+ let into_iter = vec.into_iter();
+ let debug = format!("{:?}", into_iter);
+ assert_eq!(debug, "IntoIter(['a', 'b', 'c'])");
+}
+
+#[test]
+fn test_into_iter_count() {
+ assert_eq!(vec![1, 2, 3].into_iter().count(), 3);
+}
+
+#[test]
+fn test_into_iter_clone() {
+ fn iter_equal<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
+ let v: Vec<i32> = it.collect();
+ assert_eq!(&v[..], slice);
+ }
+ let mut it = vec![1, 2, 3].into_iter();
+ iter_equal(it.clone(), &[1, 2, 3]);
+ assert_eq!(it.next(), Some(1));
+ let mut it = it.rev();
+ iter_equal(it.clone(), &[3, 2]);
+ assert_eq!(it.next(), Some(3));
+ iter_equal(it.clone(), &[2]);
+ assert_eq!(it.next(), Some(2));
+ iter_equal(it.clone(), &[]);
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_cow_from() {
+ let borrowed: &[_] = &["borrowed", "(slice)"];
+ let owned = vec!["owned", "(vec)"];
+ match (Cow::from(owned.clone()), Cow::from(borrowed)) {
+ (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
+ _ => panic!("invalid `Cow::from`"),
+ }
+}
+
+#[test]
+fn test_from_cow() {
+ let borrowed: &[_] = &["borrowed", "(slice)"];
+ let owned = vec!["owned", "(vec)"];
+ assert_eq!(Vec::from(Cow::Borrowed(borrowed)), vec!["borrowed", "(slice)"]);
+ assert_eq!(Vec::from(Cow::Owned(owned)), vec!["owned", "(vec)"]);
+}
+
+#[allow(dead_code)]
+fn assert_covariance() {
+ fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
+ d
+ }
+ fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> {
+ i
+ }
+}
+
+#[test]
+fn test_placement() {
+ let mut vec = vec![1];
+ assert_eq!(vec.place_back() <- 2, &2);
+ assert_eq!(vec.len(), 2);
+ assert_eq!(vec.place_back() <- 3, &3);
+ assert_eq!(vec.len(), 3);
+ assert_eq!(&vec, &[1, 2, 3]);
+}
+
+#[test]
+fn test_placement_panic() {
+ let mut vec = vec![1, 2, 3];
+ fn mkpanic() -> usize { panic!() }
+ let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); }));
+ assert_eq!(vec.len(), 3);
+}
+
+#[test]
+fn from_into_inner() {
+ let vec = vec![1, 2, 3];
+ let ptr = vec.as_ptr();
+ let vec = vec.into_iter().collect::<Vec<_>>();
+ assert_eq!(vec, [1, 2, 3]);
+ assert_eq!(vec.as_ptr(), ptr);
+
+ let ptr = &vec[1] as *const _;
+ let mut it = vec.into_iter();
+ it.next().unwrap();
+ let vec = it.collect::<Vec<_>>();
+ assert_eq!(vec, [2, 3]);
+ assert!(ptr != vec.as_ptr());
+}
--- /dev/null
+// Copyright 2012-2014 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.
+
+use std::collections::VecDeque;
+use std::fmt::Debug;
+use std::collections::vec_deque::{Drain};
+
+use self::Taggy::*;
+use self::Taggypar::*;
+
+#[test]
+fn test_simple() {
+ let mut d = VecDeque::new();
+ assert_eq!(d.len(), 0);
+ d.push_front(17);
+ d.push_front(42);
+ d.push_back(137);
+ assert_eq!(d.len(), 3);
+ d.push_back(137);
+ assert_eq!(d.len(), 4);
+ assert_eq!(*d.front().unwrap(), 42);
+ assert_eq!(*d.back().unwrap(), 137);
+ let mut i = d.pop_front();
+ assert_eq!(i, Some(42));
+ i = d.pop_back();
+ assert_eq!(i, Some(137));
+ i = d.pop_back();
+ assert_eq!(i, Some(137));
+ i = d.pop_back();
+ assert_eq!(i, Some(17));
+ assert_eq!(d.len(), 0);
+ d.push_back(3);
+ assert_eq!(d.len(), 1);
+ d.push_front(2);
+ assert_eq!(d.len(), 2);
+ d.push_back(4);
+ assert_eq!(d.len(), 3);
+ d.push_front(1);
+ assert_eq!(d.len(), 4);
+ assert_eq!(d[0], 1);
+ assert_eq!(d[1], 2);
+ assert_eq!(d[2], 3);
+ assert_eq!(d[3], 4);
+}
+
+#[cfg(test)]
+fn test_parameterized<T: Clone + PartialEq + Debug>(a: T, b: T, c: T, d: T) {
+ let mut deq = VecDeque::new();
+ assert_eq!(deq.len(), 0);
+ deq.push_front(a.clone());
+ deq.push_front(b.clone());
+ deq.push_back(c.clone());
+ assert_eq!(deq.len(), 3);
+ deq.push_back(d.clone());
+ assert_eq!(deq.len(), 4);
+ assert_eq!((*deq.front().unwrap()).clone(), b.clone());
+ assert_eq!((*deq.back().unwrap()).clone(), d.clone());
+ assert_eq!(deq.pop_front().unwrap(), b.clone());
+ assert_eq!(deq.pop_back().unwrap(), d.clone());
+ assert_eq!(deq.pop_back().unwrap(), c.clone());
+ assert_eq!(deq.pop_back().unwrap(), a.clone());
+ assert_eq!(deq.len(), 0);
+ deq.push_back(c.clone());
+ assert_eq!(deq.len(), 1);
+ deq.push_front(b.clone());
+ assert_eq!(deq.len(), 2);
+ deq.push_back(d.clone());
+ assert_eq!(deq.len(), 3);
+ deq.push_front(a.clone());
+ assert_eq!(deq.len(), 4);
+ assert_eq!(deq[0].clone(), a.clone());
+ assert_eq!(deq[1].clone(), b.clone());
+ assert_eq!(deq[2].clone(), c.clone());
+ assert_eq!(deq[3].clone(), d.clone());
+}
+
+#[test]
+fn test_push_front_grow() {
+ let mut deq = VecDeque::new();
+ for i in 0..66 {
+ deq.push_front(i);
+ }
+ assert_eq!(deq.len(), 66);
+
+ for i in 0..66 {
+ assert_eq!(deq[i], 65 - i);
+ }
+
+ let mut deq = VecDeque::new();
+ for i in 0..66 {
+ deq.push_back(i);
+ }
+
+ for i in 0..66 {
+ assert_eq!(deq[i], i);
+ }
+}
+
+#[test]
+fn test_index() {
+ let mut deq = VecDeque::new();
+ for i in 1..4 {
+ deq.push_front(i);
+ }
+ assert_eq!(deq[1], 2);
+}
+
+#[test]
+#[should_panic]
+fn test_index_out_of_bounds() {
+ let mut deq = VecDeque::new();
+ for i in 1..4 {
+ deq.push_front(i);
+ }
+ deq[3];
+}
+
+#[derive(Clone, PartialEq, Debug)]
+enum Taggy {
+ One(i32),
+ Two(i32, i32),
+ Three(i32, i32, i32),
+}
+
+#[derive(Clone, PartialEq, Debug)]
+enum Taggypar<T> {
+ Onepar(T),
+ Twopar(T, T),
+ Threepar(T, T, T),
+}
+
+#[derive(Clone, PartialEq, Debug)]
+struct RecCy {
+ x: i32,
+ y: i32,
+ t: Taggy,
+}
+
+#[test]
+fn test_param_int() {
+ test_parameterized::<i32>(5, 72, 64, 175);
+}
+
+#[test]
+fn test_param_taggy() {
+ test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42));
+}
+
+#[test]
+fn test_param_taggypar() {
+ test_parameterized::<Taggypar<i32>>(Onepar::<i32>(1),
+ Twopar::<i32>(1, 2),
+ Threepar::<i32>(1, 2, 3),
+ Twopar::<i32>(17, 42));
+}
+
+#[test]
+fn test_param_reccy() {
+ let reccy1 = RecCy {
+ x: 1,
+ y: 2,
+ t: One(1),
+ };
+ let reccy2 = RecCy {
+ x: 345,
+ y: 2,
+ t: Two(1, 2),
+ };
+ let reccy3 = RecCy {
+ x: 1,
+ y: 777,
+ t: Three(1, 2, 3),
+ };
+ let reccy4 = RecCy {
+ x: 19,
+ y: 252,
+ t: Two(17, 42),
+ };
+ test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4);
+}
+
+#[test]
+fn test_with_capacity() {
+ let mut d = VecDeque::with_capacity(0);
+ d.push_back(1);
+ assert_eq!(d.len(), 1);
+ let mut d = VecDeque::with_capacity(50);
+ d.push_back(1);
+ assert_eq!(d.len(), 1);
+}
+
+#[test]
+fn test_with_capacity_non_power_two() {
+ let mut d3 = VecDeque::with_capacity(3);
+ d3.push_back(1);
+
+ // X = None, | = lo
+ // [|1, X, X]
+ assert_eq!(d3.pop_front(), Some(1));
+ // [X, |X, X]
+ assert_eq!(d3.front(), None);
+
+ // [X, |3, X]
+ d3.push_back(3);
+ // [X, |3, 6]
+ d3.push_back(6);
+ // [X, X, |6]
+ assert_eq!(d3.pop_front(), Some(3));
+
+ // Pushing the lo past half way point to trigger
+ // the 'B' scenario for growth
+ // [9, X, |6]
+ d3.push_back(9);
+ // [9, 12, |6]
+ d3.push_back(12);
+
+ d3.push_back(15);
+ // There used to be a bug here about how the
+ // VecDeque made growth assumptions about the
+ // underlying Vec which didn't hold and lead
+ // to corruption.
+ // (Vec grows to next power of two)
+ // good- [9, 12, 15, X, X, X, X, |6]
+ // bug- [15, 12, X, X, X, |6, X, X]
+ assert_eq!(d3.pop_front(), Some(6));
+
+ // Which leads us to the following state which
+ // would be a failure case.
+ // bug- [15, 12, X, X, X, X, |X, X]
+ assert_eq!(d3.front(), Some(&9));
+}
+
+#[test]
+fn test_reserve_exact() {
+ let mut d = VecDeque::new();
+ d.push_back(0);
+ d.reserve_exact(50);
+ assert!(d.capacity() >= 51);
+}
+
+#[test]
+fn test_reserve() {
+ let mut d = VecDeque::new();
+ d.push_back(0);
+ d.reserve(50);
+ assert!(d.capacity() >= 51);
+}
+
+#[test]
+fn test_swap() {
+ let mut d: VecDeque<_> = (0..5).collect();
+ d.pop_front();
+ d.swap(0, 3);
+ assert_eq!(d.iter().cloned().collect::<Vec<_>>(), [4, 2, 3, 1]);
+}
+
+#[test]
+fn test_iter() {
+ let mut d = VecDeque::new();
+ assert_eq!(d.iter().next(), None);
+ assert_eq!(d.iter().size_hint(), (0, Some(0)));
+
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ {
+ let b: &[_] = &[&0, &1, &2, &3, &4];
+ assert_eq!(d.iter().collect::<Vec<_>>(), b);
+ }
+
+ for i in 6..9 {
+ d.push_front(i);
+ }
+ {
+ let b: &[_] = &[&8, &7, &6, &0, &1, &2, &3, &4];
+ assert_eq!(d.iter().collect::<Vec<_>>(), b);
+ }
+
+ let mut it = d.iter();
+ let mut len = d.len();
+ loop {
+ match it.next() {
+ None => break,
+ _ => {
+ len -= 1;
+ assert_eq!(it.size_hint(), (len, Some(len)))
+ }
+ }
+ }
+}
+
+#[test]
+fn test_rev_iter() {
+ let mut d = VecDeque::new();
+ assert_eq!(d.iter().rev().next(), None);
+
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ {
+ let b: &[_] = &[&4, &3, &2, &1, &0];
+ assert_eq!(d.iter().rev().collect::<Vec<_>>(), b);
+ }
+
+ for i in 6..9 {
+ d.push_front(i);
+ }
+ let b: &[_] = &[&4, &3, &2, &1, &0, &6, &7, &8];
+ assert_eq!(d.iter().rev().collect::<Vec<_>>(), b);
+}
+
+#[test]
+fn test_mut_rev_iter_wrap() {
+ let mut d = VecDeque::with_capacity(3);
+ assert!(d.iter_mut().rev().next().is_none());
+
+ d.push_back(1);
+ d.push_back(2);
+ d.push_back(3);
+ assert_eq!(d.pop_front(), Some(1));
+ d.push_back(4);
+
+ assert_eq!(d.iter_mut().rev().map(|x| *x).collect::<Vec<_>>(),
+ vec![4, 3, 2]);
+}
+
+#[test]
+fn test_mut_iter() {
+ let mut d = VecDeque::new();
+ assert!(d.iter_mut().next().is_none());
+
+ for i in 0..3 {
+ d.push_front(i);
+ }
+
+ for (i, elt) in d.iter_mut().enumerate() {
+ assert_eq!(*elt, 2 - i);
+ *elt = i;
+ }
+
+ {
+ let mut it = d.iter_mut();
+ assert_eq!(*it.next().unwrap(), 0);
+ assert_eq!(*it.next().unwrap(), 1);
+ assert_eq!(*it.next().unwrap(), 2);
+ assert!(it.next().is_none());
+ }
+}
+
+#[test]
+fn test_mut_rev_iter() {
+ let mut d = VecDeque::new();
+ assert!(d.iter_mut().rev().next().is_none());
+
+ for i in 0..3 {
+ d.push_front(i);
+ }
+
+ for (i, elt) in d.iter_mut().rev().enumerate() {
+ assert_eq!(*elt, i);
+ *elt = i;
+ }
+
+ {
+ let mut it = d.iter_mut().rev();
+ assert_eq!(*it.next().unwrap(), 0);
+ assert_eq!(*it.next().unwrap(), 1);
+ assert_eq!(*it.next().unwrap(), 2);
+ assert!(it.next().is_none());
+ }
+}
+
+#[test]
+fn test_into_iter() {
+
+ // Empty iter
+ {
+ let d: VecDeque<i32> = VecDeque::new();
+ let mut iter = d.into_iter();
+
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ }
+
+ // simple iter
+ {
+ let mut d = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+
+ let b = vec![0, 1, 2, 3, 4];
+ assert_eq!(d.into_iter().collect::<Vec<_>>(), b);
+ }
+
+ // wrapped iter
+ {
+ let mut d = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ for i in 6..9 {
+ d.push_front(i);
+ }
+
+ let b = vec![8, 7, 6, 0, 1, 2, 3, 4];
+ assert_eq!(d.into_iter().collect::<Vec<_>>(), b);
+ }
+
+ // partially used
+ {
+ let mut d = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ for i in 6..9 {
+ d.push_front(i);
+ }
+
+ let mut it = d.into_iter();
+ assert_eq!(it.size_hint(), (8, Some(8)));
+ assert_eq!(it.next(), Some(8));
+ assert_eq!(it.size_hint(), (7, Some(7)));
+ assert_eq!(it.next_back(), Some(4));
+ assert_eq!(it.size_hint(), (6, Some(6)));
+ assert_eq!(it.next(), Some(7));
+ assert_eq!(it.size_hint(), (5, Some(5)));
+ }
+}
+
+#[test]
+fn test_drain() {
+
+ // Empty iter
+ {
+ let mut d: VecDeque<i32> = VecDeque::new();
+
+ {
+ let mut iter = d.drain(..);
+
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ }
+
+ assert!(d.is_empty());
+ }
+
+ // simple iter
+ {
+ let mut d = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+
+ assert_eq!(d.drain(..).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
+ assert!(d.is_empty());
+ }
+
+ // wrapped iter
+ {
+ let mut d = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ for i in 6..9 {
+ d.push_front(i);
+ }
+
+ assert_eq!(d.drain(..).collect::<Vec<_>>(), [8, 7, 6, 0, 1, 2, 3, 4]);
+ assert!(d.is_empty());
+ }
+
+ // partially used
+ {
+ let mut d: VecDeque<_> = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ for i in 6..9 {
+ d.push_front(i);
+ }
+
+ {
+ let mut it = d.drain(..);
+ assert_eq!(it.size_hint(), (8, Some(8)));
+ assert_eq!(it.next(), Some(8));
+ assert_eq!(it.size_hint(), (7, Some(7)));
+ assert_eq!(it.next_back(), Some(4));
+ assert_eq!(it.size_hint(), (6, Some(6)));
+ assert_eq!(it.next(), Some(7));
+ assert_eq!(it.size_hint(), (5, Some(5)));
+ }
+ assert!(d.is_empty());
+ }
+}
+
+#[test]
+fn test_from_iter() {
+ let v = vec![1, 2, 3, 4, 5, 6, 7];
+ let deq: VecDeque<_> = v.iter().cloned().collect();
+ let u: Vec<_> = deq.iter().cloned().collect();
+ assert_eq!(u, v);
+
+ let seq = (0..).step_by(2).take(256);
+ let deq: VecDeque<_> = seq.collect();
+ for (i, &x) in deq.iter().enumerate() {
+ assert_eq!(2 * i, x);
+ }
+ assert_eq!(deq.len(), 256);
+}
+
+#[test]
+fn test_clone() {
+ let mut d = VecDeque::new();
+ d.push_front(17);
+ d.push_front(42);
+ d.push_back(137);
+ d.push_back(137);
+ assert_eq!(d.len(), 4);
+ let mut e = d.clone();
+ assert_eq!(e.len(), 4);
+ while !d.is_empty() {
+ assert_eq!(d.pop_back(), e.pop_back());
+ }
+ assert_eq!(d.len(), 0);
+ assert_eq!(e.len(), 0);
+}
+
+#[test]
+fn test_eq() {
+ let mut d = VecDeque::new();
+ assert!(d == VecDeque::with_capacity(0));
+ d.push_front(137);
+ d.push_front(17);
+ d.push_front(42);
+ d.push_back(137);
+ let mut e = VecDeque::with_capacity(0);
+ e.push_back(42);
+ e.push_back(17);
+ e.push_back(137);
+ e.push_back(137);
+ assert!(&e == &d);
+ e.pop_back();
+ e.push_back(0);
+ assert!(e != d);
+ e.clear();
+ assert!(e == VecDeque::new());
+}
+
+#[test]
+fn test_partial_eq_array() {
+ let d = VecDeque::<char>::new();
+ assert!(d == []);
+
+ let mut d = VecDeque::new();
+ d.push_front('a');
+ assert!(d == ['a']);
+
+ let mut d = VecDeque::new();
+ d.push_back('a');
+ assert!(d == ['a']);
+
+ let mut d = VecDeque::new();
+ d.push_back('a');
+ d.push_back('b');
+ assert!(d == ['a', 'b']);
+}
+
+#[test]
+fn test_hash() {
+ let mut x = VecDeque::new();
+ let mut y = VecDeque::new();
+
+ x.push_back(1);
+ x.push_back(2);
+ x.push_back(3);
+
+ y.push_back(0);
+ y.push_back(1);
+ y.pop_front();
+ y.push_back(2);
+ y.push_back(3);
+
+ assert!(::hash(&x) == ::hash(&y));
+}
+
+#[test]
+fn test_hash_after_rotation() {
+ // test that two deques hash equal even if elements are laid out differently
+ let len = 28;
+ let mut ring: VecDeque<i32> = (0..len as i32).collect();
+ let orig = ring.clone();
+ for _ in 0..ring.capacity() {
+ // shift values 1 step to the right by pop, sub one, push
+ ring.pop_front();
+ for elt in &mut ring {
+ *elt -= 1;
+ }
+ ring.push_back(len - 1);
+ assert_eq!(::hash(&orig), ::hash(&ring));
+ assert_eq!(orig, ring);
+ assert_eq!(ring, orig);
+ }
+}
+
+#[test]
+fn test_eq_after_rotation() {
+ // test that two deques are equal even if elements are laid out differently
+ let len = 28;
+ let mut ring: VecDeque<i32> = (0..len as i32).collect();
+ let mut shifted = ring.clone();
+ for _ in 0..10 {
+ // shift values 1 step to the right by pop, sub one, push
+ ring.pop_front();
+ for elt in &mut ring {
+ *elt -= 1;
+ }
+ ring.push_back(len - 1);
+ }
+
+ // try every shift
+ for _ in 0..shifted.capacity() {
+ shifted.pop_front();
+ for elt in &mut shifted {
+ *elt -= 1;
+ }
+ shifted.push_back(len - 1);
+ assert_eq!(shifted, ring);
+ assert_eq!(ring, shifted);
+ }
+}
+
+#[test]
+fn test_ord() {
+ let x = VecDeque::new();
+ let mut y = VecDeque::new();
+ y.push_back(1);
+ y.push_back(2);
+ y.push_back(3);
+ assert!(x < y);
+ assert!(y > x);
+ assert!(x <= x);
+ assert!(x >= x);
+}
+
+#[test]
+fn test_show() {
+ let ringbuf: VecDeque<_> = (0..10).collect();
+ assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+
+ let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"]
+ .iter()
+ .cloned()
+ .collect();
+ assert_eq!(format!("{:?}", ringbuf),
+ "[\"just\", \"one\", \"test\", \"more\"]");
+}
+
+#[test]
+fn test_drop() {
+ static mut DROPS: i32 = 0;
+ struct Elem;
+ impl Drop for Elem {
+ fn drop(&mut self) {
+ unsafe {
+ DROPS += 1;
+ }
+ }
+ }
+
+ let mut ring = VecDeque::new();
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+ drop(ring);
+
+ assert_eq!(unsafe { DROPS }, 4);
+}
+
+#[test]
+fn test_drop_with_pop() {
+ static mut DROPS: i32 = 0;
+ struct Elem;
+ impl Drop for Elem {
+ fn drop(&mut self) {
+ unsafe {
+ DROPS += 1;
+ }
+ }
+ }
+
+ let mut ring = VecDeque::new();
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+
+ drop(ring.pop_back());
+ drop(ring.pop_front());
+ assert_eq!(unsafe { DROPS }, 2);
+
+ drop(ring);
+ assert_eq!(unsafe { DROPS }, 4);
+}
+
+#[test]
+fn test_drop_clear() {
+ static mut DROPS: i32 = 0;
+ struct Elem;
+ impl Drop for Elem {
+ fn drop(&mut self) {
+ unsafe {
+ DROPS += 1;
+ }
+ }
+ }
+
+ let mut ring = VecDeque::new();
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+ ring.clear();
+ assert_eq!(unsafe { DROPS }, 4);
+
+ drop(ring);
+ assert_eq!(unsafe { DROPS }, 4);
+}
+
+#[test]
+fn test_reserve_grow() {
+ // test growth path A
+ // [T o o H] -> [T o o H . . . . ]
+ let mut ring = VecDeque::with_capacity(4);
+ for i in 0..3 {
+ ring.push_back(i);
+ }
+ ring.reserve(7);
+ for i in 0..3 {
+ assert_eq!(ring.pop_front(), Some(i));
+ }
+
+ // test growth path B
+ // [H T o o] -> [. T o o H . . . ]
+ let mut ring = VecDeque::with_capacity(4);
+ for i in 0..1 {
+ ring.push_back(i);
+ assert_eq!(ring.pop_front(), Some(i));
+ }
+ for i in 0..3 {
+ ring.push_back(i);
+ }
+ ring.reserve(7);
+ for i in 0..3 {
+ assert_eq!(ring.pop_front(), Some(i));
+ }
+
+ // test growth path C
+ // [o o H T] -> [o o H . . . . T ]
+ let mut ring = VecDeque::with_capacity(4);
+ for i in 0..3 {
+ ring.push_back(i);
+ assert_eq!(ring.pop_front(), Some(i));
+ }
+ for i in 0..3 {
+ ring.push_back(i);
+ }
+ ring.reserve(7);
+ for i in 0..3 {
+ assert_eq!(ring.pop_front(), Some(i));
+ }
+}
+
+#[test]
+fn test_get() {
+ let mut ring = VecDeque::new();
+ ring.push_back(0);
+ assert_eq!(ring.get(0), Some(&0));
+ assert_eq!(ring.get(1), None);
+
+ ring.push_back(1);
+ assert_eq!(ring.get(0), Some(&0));
+ assert_eq!(ring.get(1), Some(&1));
+ assert_eq!(ring.get(2), None);
+
+ ring.push_back(2);
+ assert_eq!(ring.get(0), Some(&0));
+ assert_eq!(ring.get(1), Some(&1));
+ assert_eq!(ring.get(2), Some(&2));
+ assert_eq!(ring.get(3), None);
+
+ assert_eq!(ring.pop_front(), Some(0));
+ assert_eq!(ring.get(0), Some(&1));
+ assert_eq!(ring.get(1), Some(&2));
+ assert_eq!(ring.get(2), None);
+
+ assert_eq!(ring.pop_front(), Some(1));
+ assert_eq!(ring.get(0), Some(&2));
+ assert_eq!(ring.get(1), None);
+
+ assert_eq!(ring.pop_front(), Some(2));
+ assert_eq!(ring.get(0), None);
+ assert_eq!(ring.get(1), None);
+}
+
+#[test]
+fn test_get_mut() {
+ let mut ring = VecDeque::new();
+ for i in 0..3 {
+ ring.push_back(i);
+ }
+
+ match ring.get_mut(1) {
+ Some(x) => *x = -1,
+ None => (),
+ };
+
+ assert_eq!(ring.get_mut(0), Some(&mut 0));
+ assert_eq!(ring.get_mut(1), Some(&mut -1));
+ assert_eq!(ring.get_mut(2), Some(&mut 2));
+ assert_eq!(ring.get_mut(3), None);
+
+ assert_eq!(ring.pop_front(), Some(0));
+ assert_eq!(ring.get_mut(0), Some(&mut -1));
+ assert_eq!(ring.get_mut(1), Some(&mut 2));
+ assert_eq!(ring.get_mut(2), None);
+}
+
+#[test]
+fn test_front() {
+ let mut ring = VecDeque::new();
+ ring.push_back(10);
+ ring.push_back(20);
+ assert_eq!(ring.front(), Some(&10));
+ ring.pop_front();
+ assert_eq!(ring.front(), Some(&20));
+ ring.pop_front();
+ assert_eq!(ring.front(), None);
+}
+
+#[test]
+fn test_as_slices() {
+ let mut ring: VecDeque<i32> = VecDeque::with_capacity(127);
+ let cap = ring.capacity() as i32;
+ let first = cap / 2;
+ let last = cap - first;
+ for i in 0..first {
+ ring.push_back(i);
+
+ let (left, right) = ring.as_slices();
+ let expected: Vec<_> = (0..i + 1).collect();
+ assert_eq!(left, &expected[..]);
+ assert_eq!(right, []);
+ }
+
+ for j in -last..0 {
+ ring.push_front(j);
+ let (left, right) = ring.as_slices();
+ let expected_left: Vec<_> = (-last..j + 1).rev().collect();
+ let expected_right: Vec<_> = (0..first).collect();
+ assert_eq!(left, &expected_left[..]);
+ assert_eq!(right, &expected_right[..]);
+ }
+
+ assert_eq!(ring.len() as i32, cap);
+ assert_eq!(ring.capacity() as i32, cap);
+}
+
+#[test]
+fn test_as_mut_slices() {
+ let mut ring: VecDeque<i32> = VecDeque::with_capacity(127);
+ let cap = ring.capacity() as i32;
+ let first = cap / 2;
+ let last = cap - first;
+ for i in 0..first {
+ ring.push_back(i);
+
+ let (left, right) = ring.as_mut_slices();
+ let expected: Vec<_> = (0..i + 1).collect();
+ assert_eq!(left, &expected[..]);
+ assert_eq!(right, []);
+ }
+
+ for j in -last..0 {
+ ring.push_front(j);
+ let (left, right) = ring.as_mut_slices();
+ let expected_left: Vec<_> = (-last..j + 1).rev().collect();
+ let expected_right: Vec<_> = (0..first).collect();
+ assert_eq!(left, &expected_left[..]);
+ assert_eq!(right, &expected_right[..]);
+ }
+
+ assert_eq!(ring.len() as i32, cap);
+ assert_eq!(ring.capacity() as i32, cap);
+}
+
+#[test]
+fn test_append() {
+ let mut a: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
+ let mut b: VecDeque<_> = vec![4, 5, 6].into_iter().collect();
+
+ // normal append
+ a.append(&mut b);
+ assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
+ assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []);
+
+ // append nothing to something
+ a.append(&mut b);
+ assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
+ assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []);
+
+ // append something to nothing
+ b.append(&mut a);
+ assert_eq!(b.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
+ assert_eq!(a.iter().cloned().collect::<Vec<_>>(), []);
+}
+
+#[test]
+fn test_retain() {
+ let mut buf = VecDeque::new();
+ buf.extend(1..5);
+ buf.retain(|&x| x % 2 == 0);
+ let v: Vec<_> = buf.into_iter().collect();
+ assert_eq!(&v[..], &[2, 4]);
+}
+
+#[test]
+fn test_extend_ref() {
+ let mut v = VecDeque::new();
+ v.push_back(1);
+ v.extend(&[2, 3, 4]);
+
+ assert_eq!(v.len(), 4);
+ assert_eq!(v[0], 1);
+ assert_eq!(v[1], 2);
+ assert_eq!(v[2], 3);
+ assert_eq!(v[3], 4);
+
+ let mut w = VecDeque::new();
+ w.push_back(5);
+ w.push_back(6);
+ v.extend(&w);
+
+ assert_eq!(v.len(), 6);
+ assert_eq!(v[0], 1);
+ assert_eq!(v[1], 2);
+ assert_eq!(v[2], 3);
+ assert_eq!(v[3], 4);
+ assert_eq!(v[4], 5);
+ assert_eq!(v[5], 6);
+}
+
+#[test]
+fn test_contains() {
+ let mut v = VecDeque::new();
+ v.extend(&[2, 3, 4]);
+
+ assert!(v.contains(&3));
+ assert!(!v.contains(&1));
+
+ v.clear();
+
+ assert!(!v.contains(&3));
+}
+
+#[allow(dead_code)]
+fn assert_covariance() {
+ fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
+ d
+ }
+}
+
+#[test]
+fn test_is_empty() {
+ let mut v = VecDeque::<i32>::new();
+ assert!(v.is_empty());
+ assert!(v.iter().is_empty());
+ assert!(v.iter_mut().is_empty());
+ v.extend(&[2, 3, 4]);
+ assert!(!v.is_empty());
+ assert!(!v.iter().is_empty());
+ assert!(!v.iter_mut().is_empty());
+ while let Some(_) = v.pop_front() {
+ assert_eq!(v.is_empty(), v.len() == 0);
+ assert_eq!(v.iter().is_empty(), v.iter().len() == 0);
+ assert_eq!(v.iter_mut().is_empty(), v.iter_mut().len() == 0);
+ }
+ assert!(v.is_empty());
+ assert!(v.iter().is_empty());
+ assert!(v.iter_mut().is_empty());
+ assert!(v.into_iter().is_empty());
+}
+
+#[test]
+fn test_placement_in() {
+ let mut buf: VecDeque<isize> = VecDeque::new();
+ buf.place_back() <- 1;
+ buf.place_back() <- 2;
+ assert_eq!(buf, [1,2]);
+
+ buf.place_front() <- 3;
+ buf.place_front() <- 4;
+ assert_eq!(buf, [4,3,1,2]);
+
+ {
+ let ptr_head = buf.place_front() <- 5;
+ assert_eq!(*ptr_head, 5);
+ }
+ {
+ let ptr_tail = buf.place_back() <- 6;
+ assert_eq!(*ptr_tail, 6);
+ }
+ assert_eq!(buf, [5,4,3,1,2,6]);
+}
self.len = len;
}
- /// Removes an element from anywhere in the vector and return it, replacing
- /// it with the last element.
+ /// Removes an element from the vector and returns it.
+ ///
+ /// The removed element is replaced by the last element of the vector.
///
/// This does not preserve ordering, but is O(1).
///
}
}
+ /// Returns a place for insertion at the back of the `Vec`.
+ ///
+ /// Using this method with placement syntax is equivalent to [`push`](#method.push),
+ /// but may be more efficient.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(collection_placement)]
+ /// #![feature(placement_in_syntax)]
+ ///
+ /// let mut vec = vec![1, 2];
+ /// vec.place_back() <- 3;
+ /// vec.place_back() <- 4;
+ /// assert_eq!(&vec, &[1, 2, 3, 4]);
+ /// ```
+ #[unstable(feature = "collection_placement",
+ reason = "placement protocol is subject to change",
+ issue = "30172")]
+ pub fn place_back(&mut self) -> PlaceBack<T> {
+ PlaceBack { vec: self }
+ }
+
/// Removes the last element from a vector and returns it, or [`None`] if it
/// is empty.
///
pub fn extend_from_slice(&mut self, other: &[T]) {
self.spec_extend(other.iter())
}
-
- /// Returns a place for insertion at the back of the `Vec`.
- ///
- /// Using this method with placement syntax is equivalent to [`push`](#method.push),
- /// but may be more efficient.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(collection_placement)]
- /// #![feature(placement_in_syntax)]
- ///
- /// let mut vec = vec![1, 2];
- /// vec.place_back() <- 3;
- /// vec.place_back() <- 4;
- /// assert_eq!(&vec, &[1, 2, 3, 4]);
- /// ```
- #[unstable(feature = "collection_placement",
- reason = "placement protocol is subject to change",
- issue = "30172")]
- pub fn place_back(&mut self) -> PlaceBack<T> {
- PlaceBack { vec: self }
- }
}
// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
- let diff = (self.end as usize) - (self.ptr as usize);
- let size = mem::size_of::<T>();
- let exact = diff /
- (if size == 0 {
- 1
- } else {
- size
- });
+ let exact = match self.ptr.offset_to(self.end) {
+ Some(x) => x as usize,
+ None => (self.end as usize).wrapping_sub(self.ptr as usize),
+ };
(exact, Some(exact))
}
}
}
- /// Shortens a `VecDeque`, dropping excess elements from the back.
+ /// Shortens the `VecDeque`, dropping excess elements from the back.
///
/// If `len` is greater than the `VecDeque`'s current length, this has no
/// effect.
a.contains(x) || b.contains(x)
}
- /// Provides a reference to the front element, or `None` if the sequence is
+ /// Provides a reference to the front element, or `None` if the `VecDeque` is
/// empty.
///
/// # Examples
}
/// Provides a mutable reference to the front element, or `None` if the
- /// sequence is empty.
+ /// `VecDeque` is empty.
///
/// # Examples
///
}
}
- /// Provides a reference to the back element, or `None` if the sequence is
+ /// Provides a reference to the back element, or `None` if the `VecDeque` is
/// empty.
///
/// # Examples
}
/// Provides a mutable reference to the back element, or `None` if the
- /// sequence is empty.
+ /// `VecDeque` is empty.
///
/// # Examples
///
}
}
- /// Removes the first element and returns it, or `None` if the sequence is
+ /// Removes the first element and returns it, or `None` if the `VecDeque` is
/// empty.
///
/// # Examples
}
}
- /// Inserts an element first in the sequence.
+ /// Prepends an element to the `VecDeque`.
///
/// # Examples
///
}
}
- /// Appends an element to the back of a buffer
+ /// Appends an element to the back of the `VecDeque`.
///
/// # Examples
///
unsafe { self.buffer_write(head, value) }
}
- /// Removes the last element from a buffer and returns it, or `None` if
+ /// Removes the last element from the `VecDeque` and returns it, or `None` if
/// it is empty.
///
/// # Examples
+++ /dev/null
-// Copyright 2013-2014 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.
-
-use std::panic;
-use std::collections::BinaryHeap;
-use std::collections::binary_heap::{Drain, PeekMut};
-
-#[test]
-fn test_iterator() {
- let data = vec![5, 9, 3];
- let iterout = [9, 5, 3];
- let heap = BinaryHeap::from(data);
- let mut i = 0;
- for el in &heap {
- assert_eq!(*el, iterout[i]);
- i += 1;
- }
-}
-
-#[test]
-fn test_iterator_reverse() {
- let data = vec![5, 9, 3];
- let iterout = vec![3, 5, 9];
- let pq = BinaryHeap::from(data);
-
- let v: Vec<_> = pq.iter().rev().cloned().collect();
- assert_eq!(v, iterout);
-}
-
-#[test]
-fn test_move_iter() {
- let data = vec![5, 9, 3];
- let iterout = vec![9, 5, 3];
- let pq = BinaryHeap::from(data);
-
- let v: Vec<_> = pq.into_iter().collect();
- assert_eq!(v, iterout);
-}
-
-#[test]
-fn test_move_iter_size_hint() {
- let data = vec![5, 9];
- let pq = BinaryHeap::from(data);
-
- let mut it = pq.into_iter();
-
- assert_eq!(it.size_hint(), (2, Some(2)));
- assert_eq!(it.next(), Some(9));
-
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(it.next(), Some(5));
-
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_move_iter_reverse() {
- let data = vec![5, 9, 3];
- let iterout = vec![3, 5, 9];
- let pq = BinaryHeap::from(data);
-
- let v: Vec<_> = pq.into_iter().rev().collect();
- assert_eq!(v, iterout);
-}
-
-#[test]
-fn test_peek_and_pop() {
- let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
- let mut sorted = data.clone();
- sorted.sort();
- let mut heap = BinaryHeap::from(data);
- while !heap.is_empty() {
- assert_eq!(heap.peek().unwrap(), sorted.last().unwrap());
- assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap());
- }
-}
-
-#[test]
-fn test_peek_mut() {
- let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
- let mut heap = BinaryHeap::from(data);
- assert_eq!(heap.peek(), Some(&10));
- {
- let mut top = heap.peek_mut().unwrap();
- *top -= 2;
- }
- assert_eq!(heap.peek(), Some(&9));
-}
-
-#[test]
-fn test_peek_mut_pop() {
- let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
- let mut heap = BinaryHeap::from(data);
- assert_eq!(heap.peek(), Some(&10));
- {
- let mut top = heap.peek_mut().unwrap();
- *top -= 2;
- assert_eq!(PeekMut::pop(top), 8);
- }
- assert_eq!(heap.peek(), Some(&9));
-}
-
-#[test]
-fn test_push() {
- let mut heap = BinaryHeap::from(vec![2, 4, 9]);
- assert_eq!(heap.len(), 3);
- assert!(*heap.peek().unwrap() == 9);
- heap.push(11);
- assert_eq!(heap.len(), 4);
- assert!(*heap.peek().unwrap() == 11);
- heap.push(5);
- assert_eq!(heap.len(), 5);
- assert!(*heap.peek().unwrap() == 11);
- heap.push(27);
- assert_eq!(heap.len(), 6);
- assert!(*heap.peek().unwrap() == 27);
- heap.push(3);
- assert_eq!(heap.len(), 7);
- assert!(*heap.peek().unwrap() == 27);
- heap.push(103);
- assert_eq!(heap.len(), 8);
- assert!(*heap.peek().unwrap() == 103);
-}
-
-#[test]
-fn test_push_unique() {
- let mut heap = BinaryHeap::<Box<_>>::from(vec![box 2, box 4, box 9]);
- assert_eq!(heap.len(), 3);
- assert!(*heap.peek().unwrap() == box 9);
- heap.push(box 11);
- assert_eq!(heap.len(), 4);
- assert!(*heap.peek().unwrap() == box 11);
- heap.push(box 5);
- assert_eq!(heap.len(), 5);
- assert!(*heap.peek().unwrap() == box 11);
- heap.push(box 27);
- assert_eq!(heap.len(), 6);
- assert!(*heap.peek().unwrap() == box 27);
- heap.push(box 3);
- assert_eq!(heap.len(), 7);
- assert!(*heap.peek().unwrap() == box 27);
- heap.push(box 103);
- assert_eq!(heap.len(), 8);
- assert!(*heap.peek().unwrap() == box 103);
-}
-
-#[test]
-#[allow(deprecated)]
-fn test_push_pop() {
- let mut heap = BinaryHeap::from(vec![5, 5, 2, 1, 3]);
- assert_eq!(heap.len(), 5);
- assert_eq!(heap.push_pop(6), 6);
- assert_eq!(heap.len(), 5);
- assert_eq!(heap.push_pop(0), 5);
- assert_eq!(heap.len(), 5);
- assert_eq!(heap.push_pop(4), 5);
- assert_eq!(heap.len(), 5);
- assert_eq!(heap.push_pop(1), 4);
- assert_eq!(heap.len(), 5);
-}
-
-#[test]
-#[allow(deprecated)]
-fn test_replace() {
- let mut heap = BinaryHeap::from(vec![5, 5, 2, 1, 3]);
- assert_eq!(heap.len(), 5);
- assert_eq!(heap.replace(6).unwrap(), 5);
- assert_eq!(heap.len(), 5);
- assert_eq!(heap.replace(0).unwrap(), 6);
- assert_eq!(heap.len(), 5);
- assert_eq!(heap.replace(4).unwrap(), 5);
- assert_eq!(heap.len(), 5);
- assert_eq!(heap.replace(1).unwrap(), 4);
- assert_eq!(heap.len(), 5);
-}
-
-fn check_to_vec(mut data: Vec<i32>) {
- let heap = BinaryHeap::from(data.clone());
- let mut v = heap.clone().into_vec();
- v.sort();
- data.sort();
-
- assert_eq!(v, data);
- assert_eq!(heap.into_sorted_vec(), data);
-}
-
-#[test]
-fn test_to_vec() {
- check_to_vec(vec![]);
- check_to_vec(vec![5]);
- check_to_vec(vec![3, 2]);
- check_to_vec(vec![2, 3]);
- check_to_vec(vec![5, 1, 2]);
- check_to_vec(vec![1, 100, 2, 3]);
- check_to_vec(vec![1, 3, 5, 7, 9, 2, 4, 6, 8, 0]);
- check_to_vec(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
- check_to_vec(vec![9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]);
- check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
- check_to_vec(vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
- check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]);
- check_to_vec(vec![5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]);
-}
-
-#[test]
-fn test_empty_pop() {
- let mut heap = BinaryHeap::<i32>::new();
- assert!(heap.pop().is_none());
-}
-
-#[test]
-fn test_empty_peek() {
- let empty = BinaryHeap::<i32>::new();
- assert!(empty.peek().is_none());
-}
-
-#[test]
-fn test_empty_peek_mut() {
- let mut empty = BinaryHeap::<i32>::new();
- assert!(empty.peek_mut().is_none());
-}
-
-#[test]
-#[allow(deprecated)]
-fn test_empty_replace() {
- let mut heap = BinaryHeap::new();
- assert!(heap.replace(5).is_none());
-}
-
-#[test]
-fn test_from_iter() {
- let xs = vec![9, 8, 7, 6, 5, 4, 3, 2, 1];
-
- let mut q: BinaryHeap<_> = xs.iter().rev().cloned().collect();
-
- for &x in &xs {
- assert_eq!(q.pop().unwrap(), x);
- }
-}
-
-#[test]
-fn test_drain() {
- let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect();
-
- assert_eq!(q.drain().take(5).count(), 5);
-
- assert!(q.is_empty());
-}
-
-#[test]
-fn test_extend_ref() {
- let mut a = BinaryHeap::new();
- a.push(1);
- a.push(2);
-
- a.extend(&[3, 4, 5]);
-
- assert_eq!(a.len(), 5);
- assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]);
-
- let mut a = BinaryHeap::new();
- a.push(1);
- a.push(2);
- let mut b = BinaryHeap::new();
- b.push(3);
- b.push(4);
- b.push(5);
-
- a.extend(&b);
-
- assert_eq!(a.len(), 5);
- assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]);
-}
-
-#[test]
-fn test_append() {
- let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]);
- let mut b = BinaryHeap::from(vec![-20, 5, 43]);
-
- a.append(&mut b);
-
- assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
- assert!(b.is_empty());
-}
-
-#[test]
-fn test_append_to_empty() {
- let mut a = BinaryHeap::new();
- let mut b = BinaryHeap::from(vec![-20, 5, 43]);
-
- a.append(&mut b);
-
- assert_eq!(a.into_sorted_vec(), [-20, 5, 43]);
- assert!(b.is_empty());
-}
-
-#[test]
-fn test_extend_specialization() {
- let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]);
- let b = BinaryHeap::from(vec![-20, 5, 43]);
-
- a.extend(b);
-
- assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
-}
-
-#[test]
-fn test_placement() {
- let mut a = BinaryHeap::new();
- &mut a <- 2;
- &mut a <- 4;
- &mut a <- 3;
- assert_eq!(a.peek(), Some(&4));
- assert_eq!(a.len(), 3);
- &mut a <- 1;
- assert_eq!(a.into_sorted_vec(), vec![1, 2, 3, 4]);
-}
-
-#[test]
-fn test_placement_panic() {
- let mut heap = BinaryHeap::from(vec![1, 2, 3]);
- fn mkpanic() -> usize { panic!() }
- let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { &mut heap <- mkpanic(); }));
- assert_eq!(heap.len(), 3);
-}
-
-#[allow(dead_code)]
-fn assert_covariance() {
- fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
- d
- }
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use std::collections::BTreeMap;
-use std::collections::Bound::{self, Excluded, Included, Unbounded};
-use std::collections::btree_map::Entry::{Occupied, Vacant};
-use std::rc::Rc;
-
-use std::iter::FromIterator;
-use super::DeterministicRng;
-
-#[test]
-fn test_basic_large() {
- let mut map = BTreeMap::new();
- let size = 10000;
- assert_eq!(map.len(), 0);
-
- for i in 0..size {
- assert_eq!(map.insert(i, 10 * i), None);
- assert_eq!(map.len(), i + 1);
- }
-
- for i in 0..size {
- assert_eq!(map.get(&i).unwrap(), &(i * 10));
- }
-
- for i in size..size * 2 {
- assert_eq!(map.get(&i), None);
- }
-
- for i in 0..size {
- assert_eq!(map.insert(i, 100 * i), Some(10 * i));
- assert_eq!(map.len(), size);
- }
-
- for i in 0..size {
- assert_eq!(map.get(&i).unwrap(), &(i * 100));
- }
-
- for i in 0..size / 2 {
- assert_eq!(map.remove(&(i * 2)), Some(i * 200));
- assert_eq!(map.len(), size - i - 1);
- }
-
- for i in 0..size / 2 {
- assert_eq!(map.get(&(2 * i)), None);
- assert_eq!(map.get(&(2 * i + 1)).unwrap(), &(i * 200 + 100));
- }
-
- for i in 0..size / 2 {
- assert_eq!(map.remove(&(2 * i)), None);
- assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
- assert_eq!(map.len(), size / 2 - i - 1);
- }
-}
-
-#[test]
-fn test_basic_small() {
- let mut map = BTreeMap::new();
- assert_eq!(map.remove(&1), None);
- assert_eq!(map.get(&1), None);
- assert_eq!(map.insert(1, 1), None);
- assert_eq!(map.get(&1), Some(&1));
- assert_eq!(map.insert(1, 2), Some(1));
- assert_eq!(map.get(&1), Some(&2));
- assert_eq!(map.insert(2, 4), None);
- assert_eq!(map.get(&2), Some(&4));
- assert_eq!(map.remove(&1), Some(2));
- assert_eq!(map.remove(&2), Some(4));
- assert_eq!(map.remove(&1), None);
-}
-
-#[test]
-fn test_iter() {
- let size = 10000;
-
- // Forwards
- let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- fn test<T>(size: usize, mut iter: T)
- where T: Iterator<Item = (usize, usize)>
- {
- for i in 0..size {
- assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
- assert_eq!(iter.next().unwrap(), (i, i));
- }
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
- }
- test(size, map.iter().map(|(&k, &v)| (k, v)));
- test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
- test(size, map.into_iter());
-}
-
-#[test]
-fn test_iter_rev() {
- let size = 10000;
-
- // Forwards
- let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- fn test<T>(size: usize, mut iter: T)
- where T: Iterator<Item = (usize, usize)>
- {
- for i in 0..size {
- assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
- assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1));
- }
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
- }
- test(size, map.iter().rev().map(|(&k, &v)| (k, v)));
- test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v)));
- test(size, map.into_iter().rev());
-}
-
-#[test]
-fn test_values_mut() {
- let mut a = BTreeMap::new();
- a.insert(1, String::from("hello"));
- a.insert(2, String::from("goodbye"));
-
- for value in a.values_mut() {
- value.push_str("!");
- }
-
- let values: Vec<String> = a.values().cloned().collect();
- assert_eq!(values, [String::from("hello!"), String::from("goodbye!")]);
-}
-
-#[test]
-fn test_iter_mixed() {
- let size = 10000;
-
- // Forwards
- let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- fn test<T>(size: usize, mut iter: T)
- where T: Iterator<Item = (usize, usize)> + DoubleEndedIterator
- {
- for i in 0..size / 4 {
- assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2)));
- assert_eq!(iter.next().unwrap(), (i, i));
- assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1));
- }
- for i in size / 4..size * 3 / 4 {
- assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i)));
- assert_eq!(iter.next().unwrap(), (i, i));
- }
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
- }
- test(size, map.iter().map(|(&k, &v)| (k, v)));
- test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
- test(size, map.into_iter());
-}
-
-#[test]
-fn test_range_small() {
- let size = 5;
-
- // Forwards
- let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- let mut j = 0;
- for ((&k, &v), i) in map.range(2..).zip(2..size) {
- assert_eq!(k, i);
- assert_eq!(v, i);
- j += 1;
- }
- assert_eq!(j, size - 2);
-}
-
-#[test]
-fn test_range_inclusive() {
- let size = 500;
-
- let map: BTreeMap<_, _> = (0...size).map(|i| (i, i)).collect();
-
- fn check<'a, L, R>(lhs: L, rhs: R)
- where L: IntoIterator<Item=(&'a i32, &'a i32)>,
- R: IntoIterator<Item=(&'a i32, &'a i32)>,
- {
- let lhs: Vec<_> = lhs.into_iter().collect();
- let rhs: Vec<_> = rhs.into_iter().collect();
- assert_eq!(lhs, rhs);
- }
-
- check(map.range(size + 1...size + 1), vec![]);
- check(map.range(size...size), vec![(&size, &size)]);
- check(map.range(size...size + 1), vec![(&size, &size)]);
- check(map.range(0...0), vec![(&0, &0)]);
- check(map.range(0...size - 1), map.range(..size));
- check(map.range(-1...-1), vec![]);
- check(map.range(-1...size), map.range(..));
- check(map.range(...size), map.range(..));
- check(map.range(...200), map.range(..201));
- check(map.range(5...8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
- check(map.range(-1...0), vec![(&0, &0)]);
- check(map.range(-1...2), vec![(&0, &0), (&1, &1), (&2, &2)]);
-}
-
-#[test]
-fn test_range_inclusive_max_value() {
- let max = ::std::usize::MAX;
- let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect();
-
- assert_eq!(map.range(max...max).collect::<Vec<_>>(), &[(&max, &0)]);
-}
-
-#[test]
-fn test_range_equal_empty_cases() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- assert_eq!(map.range((Included(2), Excluded(2))).next(), None);
- assert_eq!(map.range((Excluded(2), Included(2))).next(), None);
-}
-
-#[test]
-#[should_panic]
-fn test_range_equal_excluded() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- map.range((Excluded(2), Excluded(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_1() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- map.range((Included(3), Included(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_2() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- map.range((Included(3), Excluded(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_3() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- map.range((Excluded(3), Included(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_4() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- map.range((Excluded(3), Excluded(2)));
-}
-
-#[test]
-fn test_range_1000() {
- let size = 1000;
- let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- fn test(map: &BTreeMap<u32, u32>, size: u32, min: Bound<&u32>, max: Bound<&u32>) {
- let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v));
- let mut pairs = (0..size).map(|i| (i, i));
-
- for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
- assert_eq!(kv, pair);
- }
- assert_eq!(kvs.next(), None);
- assert_eq!(pairs.next(), None);
- }
- test(&map, size, Included(&0), Excluded(&size));
- test(&map, size, Unbounded, Excluded(&size));
- test(&map, size, Included(&0), Included(&(size - 1)));
- test(&map, size, Unbounded, Included(&(size - 1)));
- test(&map, size, Included(&0), Unbounded);
- test(&map, size, Unbounded, Unbounded);
-}
-
-#[test]
-fn test_range_borrowed_key() {
- let mut map = BTreeMap::new();
- map.insert("aardvark".to_string(), 1);
- map.insert("baboon".to_string(), 2);
- map.insert("coyote".to_string(), 3);
- map.insert("dingo".to_string(), 4);
- // NOTE: would like to use simply "b".."d" here...
- let mut iter = map.range::<str, _>((Included("b"),Excluded("d")));
- assert_eq!(iter.next(), Some((&"baboon".to_string(), &2)));
- assert_eq!(iter.next(), Some((&"coyote".to_string(), &3)));
- assert_eq!(iter.next(), None);
-}
-
-#[test]
-fn test_range() {
- let size = 200;
- let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- for i in 0..size {
- for j in i..size {
- let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v));
- let mut pairs = (i..j + 1).map(|i| (i, i));
-
- for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
- assert_eq!(kv, pair);
- }
- assert_eq!(kvs.next(), None);
- assert_eq!(pairs.next(), None);
- }
- }
-}
-
-#[test]
-fn test_range_mut() {
- let size = 200;
- let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- for i in 0..size {
- for j in i..size {
- let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v));
- let mut pairs = (i..j + 1).map(|i| (i, i));
-
- for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
- assert_eq!(kv, pair);
- }
- assert_eq!(kvs.next(), None);
- assert_eq!(pairs.next(), None);
- }
- }
-}
-
-#[test]
-fn test_borrow() {
- // make sure these compile -- using the Borrow trait
- {
- let mut map = BTreeMap::new();
- map.insert("0".to_string(), 1);
- assert_eq!(map["0"], 1);
- }
-
- {
- let mut map = BTreeMap::new();
- map.insert(Box::new(0), 1);
- assert_eq!(map[&0], 1);
- }
-
- {
- let mut map = BTreeMap::new();
- map.insert(Box::new([0, 1]) as Box<[i32]>, 1);
- assert_eq!(map[&[0, 1][..]], 1);
- }
-
- {
- let mut map = BTreeMap::new();
- map.insert(Rc::new(0), 1);
- assert_eq!(map[&0], 1);
- }
-}
-
-#[test]
-fn test_entry() {
- let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
-
- let mut map: BTreeMap<_, _> = xs.iter().cloned().collect();
-
- // Existing key (insert)
- match map.entry(1) {
- Vacant(_) => unreachable!(),
- Occupied(mut view) => {
- assert_eq!(view.get(), &10);
- assert_eq!(view.insert(100), 10);
- }
- }
- assert_eq!(map.get(&1).unwrap(), &100);
- assert_eq!(map.len(), 6);
-
-
- // Existing key (update)
- match map.entry(2) {
- Vacant(_) => unreachable!(),
- Occupied(mut view) => {
- let v = view.get_mut();
- *v *= 10;
- }
- }
- assert_eq!(map.get(&2).unwrap(), &200);
- assert_eq!(map.len(), 6);
-
- // Existing key (take)
- match map.entry(3) {
- Vacant(_) => unreachable!(),
- Occupied(view) => {
- assert_eq!(view.remove(), 30);
- }
- }
- assert_eq!(map.get(&3), None);
- assert_eq!(map.len(), 5);
-
-
- // Inexistent key (insert)
- match map.entry(10) {
- Occupied(_) => unreachable!(),
- Vacant(view) => {
- assert_eq!(*view.insert(1000), 1000);
- }
- }
- assert_eq!(map.get(&10).unwrap(), &1000);
- assert_eq!(map.len(), 6);
-}
-
-#[test]
-fn test_extend_ref() {
- let mut a = BTreeMap::new();
- a.insert(1, "one");
- let mut b = BTreeMap::new();
- b.insert(2, "two");
- b.insert(3, "three");
-
- a.extend(&b);
-
- assert_eq!(a.len(), 3);
- assert_eq!(a[&1], "one");
- assert_eq!(a[&2], "two");
- assert_eq!(a[&3], "three");
-}
-
-#[test]
-fn test_zst() {
- let mut m = BTreeMap::new();
- assert_eq!(m.len(), 0);
-
- assert_eq!(m.insert((), ()), None);
- assert_eq!(m.len(), 1);
-
- assert_eq!(m.insert((), ()), Some(()));
- assert_eq!(m.len(), 1);
- assert_eq!(m.iter().count(), 1);
-
- m.clear();
- assert_eq!(m.len(), 0);
-
- for _ in 0..100 {
- m.insert((), ());
- }
-
- assert_eq!(m.len(), 1);
- assert_eq!(m.iter().count(), 1);
-}
-
-// This test's only purpose is to ensure that zero-sized keys with nonsensical orderings
-// do not cause segfaults when used with zero-sized values. All other map behavior is
-// undefined.
-#[test]
-fn test_bad_zst() {
- use std::cmp::Ordering;
-
- struct Bad;
-
- impl PartialEq for Bad {
- fn eq(&self, _: &Self) -> bool {
- false
- }
- }
-
- impl Eq for Bad {}
-
- impl PartialOrd for Bad {
- fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
- Some(Ordering::Less)
- }
- }
-
- impl Ord for Bad {
- fn cmp(&self, _: &Self) -> Ordering {
- Ordering::Less
- }
- }
-
- let mut m = BTreeMap::new();
-
- for _ in 0..100 {
- m.insert(Bad, Bad);
- }
-}
-
-#[test]
-fn test_clone() {
- let mut map = BTreeMap::new();
- let size = 100;
- assert_eq!(map.len(), 0);
-
- for i in 0..size {
- assert_eq!(map.insert(i, 10 * i), None);
- assert_eq!(map.len(), i + 1);
- assert_eq!(map, map.clone());
- }
-
- for i in 0..size {
- assert_eq!(map.insert(i, 100 * i), Some(10 * i));
- assert_eq!(map.len(), size);
- assert_eq!(map, map.clone());
- }
-
- for i in 0..size / 2 {
- assert_eq!(map.remove(&(i * 2)), Some(i * 200));
- assert_eq!(map.len(), size - i - 1);
- assert_eq!(map, map.clone());
- }
-
- for i in 0..size / 2 {
- assert_eq!(map.remove(&(2 * i)), None);
- assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
- assert_eq!(map.len(), size / 2 - i - 1);
- assert_eq!(map, map.clone());
- }
-}
-
-#[test]
-#[allow(dead_code)]
-fn test_variance() {
- use std::collections::btree_map::{Iter, IntoIter, Range, Keys, Values};
-
- fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> {
- v
- }
- fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> {
- v
- }
- fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> {
- v
- }
- fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> {
- v
- }
- fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> {
- v
- }
- fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> {
- v
- }
- fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> {
- v
- }
- fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> {
- v
- }
- fn keys<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> {
- v
- }
- fn vals<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> {
- v
- }
-}
-
-#[test]
-fn test_occupied_entry_key() {
- let mut a = BTreeMap::new();
- let key = "hello there";
- let value = "value goes here";
- assert!(a.is_empty());
- a.insert(key.clone(), value.clone());
- assert_eq!(a.len(), 1);
- assert_eq!(a[key], value);
-
- match a.entry(key.clone()) {
- Vacant(_) => panic!(),
- Occupied(e) => assert_eq!(key, *e.key()),
- }
- assert_eq!(a.len(), 1);
- assert_eq!(a[key], value);
-}
-
-#[test]
-fn test_vacant_entry_key() {
- let mut a = BTreeMap::new();
- let key = "hello there";
- let value = "value goes here";
-
- assert!(a.is_empty());
- match a.entry(key.clone()) {
- Occupied(_) => panic!(),
- Vacant(e) => {
- assert_eq!(key, *e.key());
- e.insert(value.clone());
- }
- }
- assert_eq!(a.len(), 1);
- assert_eq!(a[key], value);
-}
-
-macro_rules! create_append_test {
- ($name:ident, $len:expr) => {
- #[test]
- fn $name() {
- let mut a = BTreeMap::new();
- for i in 0..8 {
- a.insert(i, i);
- }
-
- let mut b = BTreeMap::new();
- for i in 5..$len {
- b.insert(i, 2*i);
- }
-
- a.append(&mut b);
-
- assert_eq!(a.len(), $len);
- assert_eq!(b.len(), 0);
-
- for i in 0..$len {
- if i < 5 {
- assert_eq!(a[&i], i);
- } else {
- assert_eq!(a[&i], 2*i);
- }
- }
-
- assert_eq!(a.remove(&($len-1)), Some(2*($len-1)));
- assert_eq!(a.insert($len-1, 20), None);
- }
- };
-}
-
-// These are mostly for testing the algorithm that "fixes" the right edge after insertion.
-// Single node.
-create_append_test!(test_append_9, 9);
-// Two leafs that don't need fixing.
-create_append_test!(test_append_17, 17);
-// Two leafs where the second one ends up underfull and needs stealing at the end.
-create_append_test!(test_append_14, 14);
-// Two leafs where the second one ends up empty because the insertion finished at the root.
-create_append_test!(test_append_12, 12);
-// Three levels; insertion finished at the root.
-create_append_test!(test_append_144, 144);
-// Three levels; insertion finished at leaf while there is an empty node on the second level.
-create_append_test!(test_append_145, 145);
-// Tests for several randomly chosen sizes.
-create_append_test!(test_append_170, 170);
-create_append_test!(test_append_181, 181);
-create_append_test!(test_append_239, 239);
-create_append_test!(test_append_1700, 1700);
-
-fn rand_data(len: usize) -> Vec<(u32, u32)> {
- let mut rng = DeterministicRng::new();
- Vec::from_iter((0..len).map(|_| (rng.next(), rng.next())))
-}
-
-#[test]
-fn test_split_off_empty_right() {
- let mut data = rand_data(173);
-
- let mut map = BTreeMap::from_iter(data.clone());
- let right = map.split_off(&(data.iter().max().unwrap().0 + 1));
-
- data.sort();
- assert!(map.into_iter().eq(data));
- assert!(right.into_iter().eq(None));
-}
-
-#[test]
-fn test_split_off_empty_left() {
- let mut data = rand_data(314);
-
- let mut map = BTreeMap::from_iter(data.clone());
- let right = map.split_off(&data.iter().min().unwrap().0);
-
- data.sort();
- assert!(map.into_iter().eq(None));
- assert!(right.into_iter().eq(data));
-}
-
-#[test]
-fn test_split_off_large_random_sorted() {
- let mut data = rand_data(1529);
- // special case with maximum height.
- data.sort();
-
- let mut map = BTreeMap::from_iter(data.clone());
- let key = data[data.len() / 2].0;
- let right = map.split_off(&key);
-
- assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key)));
- assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key)));
-}
+++ /dev/null
-// Copyright 2014 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.
-
-mod map;
-mod set;
-
-/// XorShiftRng
-struct DeterministicRng {
- x: u32,
- y: u32,
- z: u32,
- w: u32,
-}
-
-impl DeterministicRng {
- fn new() -> Self {
- DeterministicRng {
- x: 0x193a6754,
- y: 0xa8a7d469,
- z: 0x97830e05,
- w: 0x113ba7bb,
- }
- }
-
- fn next(&mut self) -> u32 {
- let x = self.x;
- let t = x ^ (x << 11);
- self.x = self.y;
- self.y = self.z;
- self.z = self.w;
- let w_ = self.w;
- self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
- self.w
- }
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use std::collections::BTreeSet;
-
-use std::iter::FromIterator;
-use super::DeterministicRng;
-
-#[test]
-fn test_clone_eq() {
- let mut m = BTreeSet::new();
-
- m.insert(1);
- m.insert(2);
-
- assert!(m.clone() == m);
-}
-
-#[test]
-fn test_hash() {
- let mut x = BTreeSet::new();
- let mut y = BTreeSet::new();
-
- x.insert(1);
- x.insert(2);
- x.insert(3);
-
- y.insert(3);
- y.insert(2);
- y.insert(1);
-
- assert!(::hash(&x) == ::hash(&y));
-}
-
-fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F)
- where F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut FnMut(&i32) -> bool) -> bool
-{
- let mut set_a = BTreeSet::new();
- let mut set_b = BTreeSet::new();
-
- for x in a {
- assert!(set_a.insert(*x))
- }
- for y in b {
- assert!(set_b.insert(*y))
- }
-
- let mut i = 0;
- f(&set_a,
- &set_b,
- &mut |&x| {
- assert_eq!(x, expected[i]);
- i += 1;
- true
- });
- assert_eq!(i, expected.len());
-}
-
-#[test]
-fn test_intersection() {
- fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) {
- check(a, b, expected, |x, y, f| x.intersection(y).all(f))
- }
-
- check_intersection(&[], &[], &[]);
- check_intersection(&[1, 2, 3], &[], &[]);
- check_intersection(&[], &[1, 2, 3], &[]);
- check_intersection(&[2], &[1, 2, 3], &[2]);
- check_intersection(&[1, 2, 3], &[2], &[2]);
- check_intersection(&[11, 1, 3, 77, 103, 5, -5],
- &[2, 11, 77, -9, -42, 5, 3],
- &[3, 5, 11, 77]);
-}
-
-#[test]
-fn test_difference() {
- fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) {
- check(a, b, expected, |x, y, f| x.difference(y).all(f))
- }
-
- check_difference(&[], &[], &[]);
- check_difference(&[1, 12], &[], &[1, 12]);
- check_difference(&[], &[1, 2, 3, 9], &[]);
- check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]);
- check_difference(&[-5, 11, 22, 33, 40, 42],
- &[-12, -5, 14, 23, 34, 38, 39, 50],
- &[11, 22, 33, 40, 42]);
-}
-
-#[test]
-fn test_symmetric_difference() {
- fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) {
- check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f))
- }
-
- check_symmetric_difference(&[], &[], &[]);
- check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]);
- check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]);
- check_symmetric_difference(&[1, 3, 5, 9, 11],
- &[-2, 3, 9, 14, 22],
- &[-2, 1, 5, 11, 14, 22]);
-}
-
-#[test]
-fn test_union() {
- fn check_union(a: &[i32], b: &[i32], expected: &[i32]) {
- check(a, b, expected, |x, y, f| x.union(y).all(f))
- }
-
- check_union(&[], &[], &[]);
- check_union(&[1, 2, 3], &[2], &[1, 2, 3]);
- check_union(&[2], &[1, 2, 3], &[1, 2, 3]);
- check_union(&[1, 3, 5, 9, 11, 16, 19, 24],
- &[-2, 1, 5, 9, 13, 19],
- &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]);
-}
-
-#[test]
-fn test_zip() {
- let mut x = BTreeSet::new();
- x.insert(5);
- x.insert(12);
- x.insert(11);
-
- let mut y = BTreeSet::new();
- y.insert("foo");
- y.insert("bar");
-
- let x = x;
- let y = y;
- let mut z = x.iter().zip(&y);
-
- assert_eq!(z.next().unwrap(), (&5, &("bar")));
- assert_eq!(z.next().unwrap(), (&11, &("foo")));
- assert!(z.next().is_none());
-}
-
-#[test]
-fn test_from_iter() {
- let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
-
- let set: BTreeSet<_> = xs.iter().cloned().collect();
-
- for x in &xs {
- assert!(set.contains(x));
- }
-}
-
-#[test]
-fn test_show() {
- let mut set = BTreeSet::new();
- let empty = BTreeSet::<i32>::new();
-
- set.insert(1);
- set.insert(2);
-
- let set_str = format!("{:?}", set);
-
- assert_eq!(set_str, "{1, 2}");
- assert_eq!(format!("{:?}", empty), "{}");
-}
-
-#[test]
-fn test_extend_ref() {
- let mut a = BTreeSet::new();
- a.insert(1);
-
- a.extend(&[2, 3, 4]);
-
- assert_eq!(a.len(), 4);
- assert!(a.contains(&1));
- assert!(a.contains(&2));
- assert!(a.contains(&3));
- assert!(a.contains(&4));
-
- let mut b = BTreeSet::new();
- b.insert(5);
- b.insert(6);
-
- a.extend(&b);
-
- assert_eq!(a.len(), 6);
- assert!(a.contains(&1));
- assert!(a.contains(&2));
- assert!(a.contains(&3));
- assert!(a.contains(&4));
- assert!(a.contains(&5));
- assert!(a.contains(&6));
-}
-
-#[test]
-fn test_recovery() {
- use std::cmp::Ordering;
-
- #[derive(Debug)]
- struct Foo(&'static str, i32);
-
- impl PartialEq for Foo {
- fn eq(&self, other: &Self) -> bool {
- self.0 == other.0
- }
- }
-
- impl Eq for Foo {}
-
- impl PartialOrd for Foo {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- self.0.partial_cmp(&other.0)
- }
- }
-
- impl Ord for Foo {
- fn cmp(&self, other: &Self) -> Ordering {
- self.0.cmp(&other.0)
- }
- }
-
- let mut s = BTreeSet::new();
- assert_eq!(s.replace(Foo("a", 1)), None);
- assert_eq!(s.len(), 1);
- assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1)));
- assert_eq!(s.len(), 1);
-
- {
- let mut it = s.iter();
- assert_eq!(it.next(), Some(&Foo("a", 2)));
- assert_eq!(it.next(), None);
- }
-
- assert_eq!(s.get(&Foo("a", 1)), Some(&Foo("a", 2)));
- assert_eq!(s.take(&Foo("a", 1)), Some(Foo("a", 2)));
- assert_eq!(s.len(), 0);
-
- assert_eq!(s.get(&Foo("a", 1)), None);
- assert_eq!(s.take(&Foo("a", 1)), None);
-
- assert_eq!(s.iter().next(), None);
-}
-
-#[test]
-#[allow(dead_code)]
-fn test_variance() {
- use std::collections::btree_set::{IntoIter, Iter, Range};
-
- fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> {
- v
- }
- fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
- v
- }
- fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> {
- v
- }
- fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> {
- v
- }
-}
-
-#[test]
-fn test_append() {
- let mut a = BTreeSet::new();
- a.insert(1);
- a.insert(2);
- a.insert(3);
-
- let mut b = BTreeSet::new();
- b.insert(3);
- b.insert(4);
- b.insert(5);
-
- a.append(&mut b);
-
- assert_eq!(a.len(), 5);
- assert_eq!(b.len(), 0);
-
- assert_eq!(a.contains(&1), true);
- assert_eq!(a.contains(&2), true);
- assert_eq!(a.contains(&3), true);
- assert_eq!(a.contains(&4), true);
- assert_eq!(a.contains(&5), true);
-}
-
-fn rand_data(len: usize) -> Vec<u32> {
- let mut rng = DeterministicRng::new();
- Vec::from_iter((0..len).map(|_| rng.next()))
-}
-
-#[test]
-fn test_split_off_empty_right() {
- let mut data = rand_data(173);
-
- let mut set = BTreeSet::from_iter(data.clone());
- let right = set.split_off(&(data.iter().max().unwrap() + 1));
-
- data.sort();
- assert!(set.into_iter().eq(data));
- assert!(right.into_iter().eq(None));
-}
-
-#[test]
-fn test_split_off_empty_left() {
- let mut data = rand_data(314);
-
- let mut set = BTreeSet::from_iter(data.clone());
- let right = set.split_off(data.iter().min().unwrap());
-
- data.sort();
- assert!(set.into_iter().eq(None));
- assert!(right.into_iter().eq(data));
-}
-
-#[test]
-fn test_split_off_large_random_sorted() {
- let mut data = rand_data(1529);
- // special case with maximum height.
- data.sort();
-
- let mut set = BTreeSet::from_iter(data.clone());
- let key = data[data.len() / 2];
- let right = set.split_off(&key);
-
- assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key)));
- assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key)));
-}
+++ /dev/null
-// Copyright 2016 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.
-
-use std::borrow::Cow;
-
-// check that Cow<'a, str> implements addition
-#[test]
-fn check_cow_add_cow() {
- let borrowed1 = Cow::Borrowed("Hello, ");
- let borrowed2 = Cow::Borrowed("World!");
- let borrow_empty = Cow::Borrowed("");
-
- let owned1: Cow<str> = Cow::Owned(String::from("Hi, "));
- let owned2: Cow<str> = Cow::Owned(String::from("Rustaceans!"));
- let owned_empty: Cow<str> = Cow::Owned(String::new());
-
- assert_eq!("Hello, World!", borrowed1.clone() + borrowed2.clone());
- assert_eq!("Hello, Rustaceans!", borrowed1.clone() + owned2.clone());
-
- assert_eq!("Hi, World!", owned1.clone() + borrowed2.clone());
- assert_eq!("Hi, Rustaceans!", owned1.clone() + owned2.clone());
-
- if let Cow::Owned(_) = borrowed1.clone() + borrow_empty.clone() {
- panic!("Adding empty strings to a borrow should note allocate");
- }
- if let Cow::Owned(_) = borrow_empty.clone() + borrowed1.clone() {
- panic!("Adding empty strings to a borrow should note allocate");
- }
- if let Cow::Owned(_) = borrowed1.clone() + owned_empty.clone() {
- panic!("Adding empty strings to a borrow should note allocate");
- }
- if let Cow::Owned(_) = owned_empty.clone() + borrowed1.clone() {
- panic!("Adding empty strings to a borrow should note allocate");
- }
-}
-
-#[test]
-fn check_cow_add_str() {
- let borrowed = Cow::Borrowed("Hello, ");
- let borrow_empty = Cow::Borrowed("");
-
- let owned: Cow<str> = Cow::Owned(String::from("Hi, "));
- let owned_empty: Cow<str> = Cow::Owned(String::new());
-
- assert_eq!("Hello, World!", borrowed.clone() + "World!");
-
- assert_eq!("Hi, World!", owned.clone() + "World!");
-
- if let Cow::Owned(_) = borrowed.clone() + "" {
- panic!("Adding empty strings to a borrow should note allocate");
- }
- if let Cow::Owned(_) = borrow_empty.clone() + "Hello, " {
- panic!("Adding empty strings to a borrow should note allocate");
- }
- if let Cow::Owned(_) = owned_empty.clone() + "Hello, " {
- panic!("Adding empty strings to a borrow should note allocate");
- }
-}
-
-#[test]
-fn check_cow_add_assign_cow() {
- let mut borrowed1 = Cow::Borrowed("Hello, ");
- let borrowed2 = Cow::Borrowed("World!");
- let borrow_empty = Cow::Borrowed("");
-
- let mut owned1: Cow<str> = Cow::Owned(String::from("Hi, "));
- let owned2: Cow<str> = Cow::Owned(String::from("Rustaceans!"));
- let owned_empty: Cow<str> = Cow::Owned(String::new());
-
- let mut s = borrowed1.clone();
- s += borrow_empty.clone();
- assert_eq!("Hello, ", s);
- if let Cow::Owned(_) = s {
- panic!("Adding empty strings to a borrow should note allocate");
- }
- let mut s = borrow_empty.clone();
- s += borrowed1.clone();
- assert_eq!("Hello, ", s);
- if let Cow::Owned(_) = s {
- panic!("Adding empty strings to a borrow should note allocate");
- }
- let mut s = borrowed1.clone();
- s += owned_empty.clone();
- assert_eq!("Hello, ", s);
- if let Cow::Owned(_) = s {
- panic!("Adding empty strings to a borrow should note allocate");
- }
- let mut s = owned_empty.clone();
- s += borrowed1.clone();
- assert_eq!("Hello, ", s);
- if let Cow::Owned(_) = s {
- panic!("Adding empty strings to a borrow should note allocate");
- }
-
- owned1 += borrowed2;
- borrowed1 += owned2;
-
- assert_eq!("Hi, World!", owned1);
- assert_eq!("Hello, Rustaceans!", borrowed1);
-}
-
-#[test]
-fn check_cow_add_assign_str() {
- let mut borrowed = Cow::Borrowed("Hello, ");
- let borrow_empty = Cow::Borrowed("");
-
- let mut owned: Cow<str> = Cow::Owned(String::from("Hi, "));
- let owned_empty: Cow<str> = Cow::Owned(String::new());
-
- let mut s = borrowed.clone();
- s += "";
- assert_eq!("Hello, ", s);
- if let Cow::Owned(_) = s {
- panic!("Adding empty strings to a borrow should note allocate");
- }
- let mut s = borrow_empty.clone();
- s += "World!";
- assert_eq!("World!", s);
- if let Cow::Owned(_) = s {
- panic!("Adding empty strings to a borrow should note allocate");
- }
- let mut s = owned_empty.clone();
- s += "World!";
- assert_eq!("World!", s);
- if let Cow::Owned(_) = s {
- panic!("Adding empty strings to a borrow should note allocate");
- }
-
- owned += "World!";
- borrowed += "World!";
-
- assert_eq!("Hi, World!", owned);
- assert_eq!("Hello, World!", borrowed);
-}
+++ /dev/null
-// Copyright 2013-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.
-
-use std::fmt;
-
-#[test]
-fn test_format() {
- let s = fmt::format(format_args!("Hello, {}!", "world"));
- assert_eq!(s, "Hello, world!");
-}
+++ /dev/null
-// Copyright 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.
-
-#![deny(warnings)]
-
-#![feature(binary_heap_extras)]
-#![feature(binary_heap_peek_mut_pop)]
-#![feature(box_syntax)]
-#![feature(inclusive_range_syntax)]
-#![feature(collection_placement)]
-#![feature(collections)]
-#![feature(const_fn)]
-#![feature(exact_size_is_empty)]
-#![feature(pattern)]
-#![feature(placement_in_syntax)]
-#![feature(rand)]
-#![feature(step_by)]
-#![feature(str_escape)]
-#![feature(test)]
-#![feature(unboxed_closures)]
-#![feature(unicode)]
-#![feature(utf8_error_error_len)]
-
-extern crate collections;
-extern crate test;
-extern crate std_unicode;
-extern crate core;
-
-use std::hash::{Hash, Hasher};
-use std::collections::hash_map::DefaultHasher;
-
-mod binary_heap;
-mod btree;
-mod cow_str;
-mod fmt;
-mod linked_list;
-mod slice;
-mod str;
-mod string;
-mod vec_deque;
-mod vec;
-
-fn hash<T: Hash>(t: &T) -> u64 {
- let mut s = DefaultHasher::new();
- t.hash(&mut s);
- s.finish()
-}
+++ /dev/null
-// 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.
-
-use std::collections::LinkedList;
-
-#[test]
-fn test_basic() {
- let mut m = LinkedList::<Box<_>>::new();
- assert_eq!(m.pop_front(), None);
- assert_eq!(m.pop_back(), None);
- assert_eq!(m.pop_front(), None);
- m.push_front(box 1);
- assert_eq!(m.pop_front(), Some(box 1));
- m.push_back(box 2);
- m.push_back(box 3);
- assert_eq!(m.len(), 2);
- assert_eq!(m.pop_front(), Some(box 2));
- assert_eq!(m.pop_front(), Some(box 3));
- assert_eq!(m.len(), 0);
- assert_eq!(m.pop_front(), None);
- m.push_back(box 1);
- m.push_back(box 3);
- m.push_back(box 5);
- m.push_back(box 7);
- assert_eq!(m.pop_front(), Some(box 1));
-
- let mut n = LinkedList::new();
- n.push_front(2);
- n.push_front(3);
- {
- assert_eq!(n.front().unwrap(), &3);
- let x = n.front_mut().unwrap();
- assert_eq!(*x, 3);
- *x = 0;
- }
- {
- assert_eq!(n.back().unwrap(), &2);
- let y = n.back_mut().unwrap();
- assert_eq!(*y, 2);
- *y = 1;
- }
- assert_eq!(n.pop_front(), Some(0));
- assert_eq!(n.pop_front(), Some(1));
-}
-
-#[cfg(test)]
-fn generate_test() -> LinkedList<i32> {
- list_from(&[0, 1, 2, 3, 4, 5, 6])
-}
-
-#[cfg(test)]
-fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> {
- v.iter().cloned().collect()
-}
-
-#[test]
-fn test_split_off() {
- // singleton
- {
- let mut m = LinkedList::new();
- m.push_back(1);
-
- let p = m.split_off(0);
- assert_eq!(m.len(), 0);
- assert_eq!(p.len(), 1);
- assert_eq!(p.back(), Some(&1));
- assert_eq!(p.front(), Some(&1));
- }
-
- // not singleton, forwards
- {
- let u = vec![1, 2, 3, 4, 5];
- let mut m = list_from(&u);
- let mut n = m.split_off(2);
- assert_eq!(m.len(), 2);
- assert_eq!(n.len(), 3);
- for elt in 1..3 {
- assert_eq!(m.pop_front(), Some(elt));
- }
- for elt in 3..6 {
- assert_eq!(n.pop_front(), Some(elt));
- }
- }
- // not singleton, backwards
- {
- let u = vec![1, 2, 3, 4, 5];
- let mut m = list_from(&u);
- let mut n = m.split_off(4);
- assert_eq!(m.len(), 4);
- assert_eq!(n.len(), 1);
- for elt in 1..5 {
- assert_eq!(m.pop_front(), Some(elt));
- }
- for elt in 5..6 {
- assert_eq!(n.pop_front(), Some(elt));
- }
- }
-
- // no-op on the last index
- {
- let mut m = LinkedList::new();
- m.push_back(1);
-
- let p = m.split_off(1);
- assert_eq!(m.len(), 1);
- assert_eq!(p.len(), 0);
- assert_eq!(m.back(), Some(&1));
- assert_eq!(m.front(), Some(&1));
- }
-
-}
-
-#[test]
-fn test_iterator() {
- let m = generate_test();
- for (i, elt) in m.iter().enumerate() {
- assert_eq!(i as i32, *elt);
- }
- let mut n = LinkedList::new();
- assert_eq!(n.iter().next(), None);
- n.push_front(4);
- let mut it = n.iter();
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(it.next().unwrap(), &4);
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_iterator_clone() {
- let mut n = LinkedList::new();
- n.push_back(2);
- n.push_back(3);
- n.push_back(4);
- let mut it = n.iter();
- it.next();
- let mut jt = it.clone();
- assert_eq!(it.next(), jt.next());
- assert_eq!(it.next_back(), jt.next_back());
- assert_eq!(it.next(), jt.next());
-}
-
-#[test]
-fn test_iterator_double_end() {
- let mut n = LinkedList::new();
- assert_eq!(n.iter().next(), None);
- n.push_front(4);
- n.push_front(5);
- n.push_front(6);
- let mut it = n.iter();
- assert_eq!(it.size_hint(), (3, Some(3)));
- assert_eq!(it.next().unwrap(), &6);
- assert_eq!(it.size_hint(), (2, Some(2)));
- assert_eq!(it.next_back().unwrap(), &4);
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(it.next_back().unwrap(), &5);
- assert_eq!(it.next_back(), None);
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_rev_iter() {
- let m = generate_test();
- for (i, elt) in m.iter().rev().enumerate() {
- assert_eq!((6 - i) as i32, *elt);
- }
- let mut n = LinkedList::new();
- assert_eq!(n.iter().rev().next(), None);
- n.push_front(4);
- let mut it = n.iter().rev();
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(it.next().unwrap(), &4);
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_mut_iter() {
- let mut m = generate_test();
- let mut len = m.len();
- for (i, elt) in m.iter_mut().enumerate() {
- assert_eq!(i as i32, *elt);
- len -= 1;
- }
- assert_eq!(len, 0);
- let mut n = LinkedList::new();
- assert!(n.iter_mut().next().is_none());
- n.push_front(4);
- n.push_back(5);
- let mut it = n.iter_mut();
- assert_eq!(it.size_hint(), (2, Some(2)));
- assert!(it.next().is_some());
- assert!(it.next().is_some());
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert!(it.next().is_none());
-}
-
-#[test]
-fn test_iterator_mut_double_end() {
- let mut n = LinkedList::new();
- assert!(n.iter_mut().next_back().is_none());
- n.push_front(4);
- n.push_front(5);
- n.push_front(6);
- let mut it = n.iter_mut();
- assert_eq!(it.size_hint(), (3, Some(3)));
- assert_eq!(*it.next().unwrap(), 6);
- assert_eq!(it.size_hint(), (2, Some(2)));
- assert_eq!(*it.next_back().unwrap(), 4);
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(*it.next_back().unwrap(), 5);
- assert!(it.next_back().is_none());
- assert!(it.next().is_none());
-}
-
-#[test]
-fn test_mut_rev_iter() {
- let mut m = generate_test();
- for (i, elt) in m.iter_mut().rev().enumerate() {
- assert_eq!((6 - i) as i32, *elt);
- }
- let mut n = LinkedList::new();
- assert!(n.iter_mut().rev().next().is_none());
- n.push_front(4);
- let mut it = n.iter_mut().rev();
- assert!(it.next().is_some());
- assert!(it.next().is_none());
-}
-
-#[test]
-fn test_eq() {
- let mut n = list_from(&[]);
- let mut m = list_from(&[]);
- assert!(n == m);
- n.push_front(1);
- assert!(n != m);
- m.push_back(1);
- assert!(n == m);
-
- let n = list_from(&[2, 3, 4]);
- let m = list_from(&[1, 2, 3]);
- assert!(n != m);
-}
-
-#[test]
-fn test_hash() {
- let mut x = LinkedList::new();
- let mut y = LinkedList::new();
-
- assert!(::hash(&x) == ::hash(&y));
-
- x.push_back(1);
- x.push_back(2);
- x.push_back(3);
-
- y.push_front(3);
- y.push_front(2);
- y.push_front(1);
-
- assert!(::hash(&x) == ::hash(&y));
-}
-
-#[test]
-fn test_ord() {
- let n = list_from(&[]);
- let m = list_from(&[1, 2, 3]);
- assert!(n < m);
- assert!(m > n);
- assert!(n <= n);
- assert!(n >= n);
-}
-
-#[test]
-fn test_ord_nan() {
- let nan = 0.0f64 / 0.0;
- let n = list_from(&[nan]);
- let m = list_from(&[nan]);
- assert!(!(n < m));
- assert!(!(n > m));
- assert!(!(n <= m));
- assert!(!(n >= m));
-
- let n = list_from(&[nan]);
- let one = list_from(&[1.0f64]);
- assert!(!(n < one));
- assert!(!(n > one));
- assert!(!(n <= one));
- assert!(!(n >= one));
-
- let u = list_from(&[1.0f64, 2.0, nan]);
- let v = list_from(&[1.0f64, 2.0, 3.0]);
- assert!(!(u < v));
- assert!(!(u > v));
- assert!(!(u <= v));
- assert!(!(u >= v));
-
- let s = list_from(&[1.0f64, 2.0, 4.0, 2.0]);
- let t = list_from(&[1.0f64, 2.0, 3.0, 2.0]);
- assert!(!(s < t));
- assert!(s > one);
- assert!(!(s <= one));
- assert!(s >= one);
-}
-
-#[test]
-fn test_show() {
- let list: LinkedList<_> = (0..10).collect();
- assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
-
- let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect();
- assert_eq!(format!("{:?}", list),
- "[\"just\", \"one\", \"test\", \"more\"]");
-}
-
-#[test]
-fn test_extend_ref() {
- let mut a = LinkedList::new();
- a.push_back(1);
-
- a.extend(&[2, 3, 4]);
-
- assert_eq!(a.len(), 4);
- assert_eq!(a, list_from(&[1, 2, 3, 4]));
-
- let mut b = LinkedList::new();
- b.push_back(5);
- b.push_back(6);
- a.extend(&b);
-
- assert_eq!(a.len(), 6);
- assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6]));
-}
-
-#[test]
-fn test_extend() {
- let mut a = LinkedList::new();
- a.push_back(1);
- a.extend(vec![2, 3, 4]); // uses iterator
-
- assert_eq!(a.len(), 4);
- assert!(a.iter().eq(&[1, 2, 3, 4]));
-
- let b: LinkedList<_> = vec![5, 6, 7].into_iter().collect();
- a.extend(b); // specializes to `append`
-
- assert_eq!(a.len(), 7);
- assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7]));
-}
-
-#[test]
-fn test_contains() {
- let mut l = LinkedList::new();
- l.extend(&[2, 3, 4]);
-
- assert!(l.contains(&3));
- assert!(!l.contains(&1));
-
- l.clear();
-
- assert!(!l.contains(&3));
-}
+++ /dev/null
-// 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.
-
-use std::cmp::Ordering::{Equal, Greater, Less};
-use std::mem;
-use std::__rand::{Rng, thread_rng};
-use std::rc::Rc;
-
-fn square(n: usize) -> usize {
- n * n
-}
-
-fn is_odd(n: &usize) -> bool {
- *n % 2 == 1
-}
-
-#[test]
-fn test_from_fn() {
- // Test on-stack from_fn.
- let mut v: Vec<_> = (0..3).map(square).collect();
- {
- let v = v;
- assert_eq!(v.len(), 3);
- assert_eq!(v[0], 0);
- assert_eq!(v[1], 1);
- assert_eq!(v[2], 4);
- }
-
- // Test on-heap from_fn.
- v = (0..5).map(square).collect();
- {
- let v = v;
- assert_eq!(v.len(), 5);
- assert_eq!(v[0], 0);
- assert_eq!(v[1], 1);
- assert_eq!(v[2], 4);
- assert_eq!(v[3], 9);
- assert_eq!(v[4], 16);
- }
-}
-
-#[test]
-fn test_from_elem() {
- // Test on-stack from_elem.
- let mut v = vec![10, 10];
- {
- let v = v;
- assert_eq!(v.len(), 2);
- assert_eq!(v[0], 10);
- assert_eq!(v[1], 10);
- }
-
- // Test on-heap from_elem.
- v = vec![20; 6];
- {
- let v = &v[..];
- assert_eq!(v[0], 20);
- assert_eq!(v[1], 20);
- assert_eq!(v[2], 20);
- assert_eq!(v[3], 20);
- assert_eq!(v[4], 20);
- assert_eq!(v[5], 20);
- }
-}
-
-#[test]
-fn test_is_empty() {
- let xs: [i32; 0] = [];
- assert!(xs.is_empty());
- assert!(![0].is_empty());
-}
-
-#[test]
-fn test_len_divzero() {
- type Z = [i8; 0];
- let v0: &[Z] = &[];
- let v1: &[Z] = &[[]];
- let v2: &[Z] = &[[], []];
- assert_eq!(mem::size_of::<Z>(), 0);
- assert_eq!(v0.len(), 0);
- assert_eq!(v1.len(), 1);
- assert_eq!(v2.len(), 2);
-}
-
-#[test]
-fn test_get() {
- let mut a = vec![11];
- assert_eq!(a.get(1), None);
- a = vec![11, 12];
- assert_eq!(a.get(1).unwrap(), &12);
- a = vec![11, 12, 13];
- assert_eq!(a.get(1).unwrap(), &12);
-}
-
-#[test]
-fn test_first() {
- let mut a = vec![];
- assert_eq!(a.first(), None);
- a = vec![11];
- assert_eq!(a.first().unwrap(), &11);
- a = vec![11, 12];
- assert_eq!(a.first().unwrap(), &11);
-}
-
-#[test]
-fn test_first_mut() {
- let mut a = vec![];
- assert_eq!(a.first_mut(), None);
- a = vec![11];
- assert_eq!(*a.first_mut().unwrap(), 11);
- a = vec![11, 12];
- assert_eq!(*a.first_mut().unwrap(), 11);
-}
-
-#[test]
-fn test_split_first() {
- let mut a = vec![11];
- let b: &[i32] = &[];
- assert!(b.split_first().is_none());
- assert_eq!(a.split_first(), Some((&11, b)));
- a = vec![11, 12];
- let b: &[i32] = &[12];
- assert_eq!(a.split_first(), Some((&11, b)));
-}
-
-#[test]
-fn test_split_first_mut() {
- let mut a = vec![11];
- let b: &mut [i32] = &mut [];
- assert!(b.split_first_mut().is_none());
- assert!(a.split_first_mut() == Some((&mut 11, b)));
- a = vec![11, 12];
- let b: &mut [_] = &mut [12];
- assert!(a.split_first_mut() == Some((&mut 11, b)));
-}
-
-#[test]
-fn test_split_last() {
- let mut a = vec![11];
- let b: &[i32] = &[];
- assert!(b.split_last().is_none());
- assert_eq!(a.split_last(), Some((&11, b)));
- a = vec![11, 12];
- let b: &[_] = &[11];
- assert_eq!(a.split_last(), Some((&12, b)));
-}
-
-#[test]
-fn test_split_last_mut() {
- let mut a = vec![11];
- let b: &mut [i32] = &mut [];
- assert!(b.split_last_mut().is_none());
- assert!(a.split_last_mut() == Some((&mut 11, b)));
-
- a = vec![11, 12];
- let b: &mut [_] = &mut [11];
- assert!(a.split_last_mut() == Some((&mut 12, b)));
-}
-
-#[test]
-fn test_last() {
- let mut a = vec![];
- assert_eq!(a.last(), None);
- a = vec![11];
- assert_eq!(a.last().unwrap(), &11);
- a = vec![11, 12];
- assert_eq!(a.last().unwrap(), &12);
-}
-
-#[test]
-fn test_last_mut() {
- let mut a = vec![];
- assert_eq!(a.last_mut(), None);
- a = vec![11];
- assert_eq!(*a.last_mut().unwrap(), 11);
- a = vec![11, 12];
- assert_eq!(*a.last_mut().unwrap(), 12);
-}
-
-#[test]
-fn test_slice() {
- // Test fixed length vector.
- let vec_fixed = [1, 2, 3, 4];
- let v_a = vec_fixed[1..vec_fixed.len()].to_vec();
- assert_eq!(v_a.len(), 3);
-
- assert_eq!(v_a[0], 2);
- assert_eq!(v_a[1], 3);
- assert_eq!(v_a[2], 4);
-
- // Test on stack.
- let vec_stack: &[_] = &[1, 2, 3];
- let v_b = vec_stack[1..3].to_vec();
- assert_eq!(v_b.len(), 2);
-
- assert_eq!(v_b[0], 2);
- assert_eq!(v_b[1], 3);
-
- // Test `Box<[T]>`
- let vec_unique = vec![1, 2, 3, 4, 5, 6];
- let v_d = vec_unique[1..6].to_vec();
- assert_eq!(v_d.len(), 5);
-
- assert_eq!(v_d[0], 2);
- assert_eq!(v_d[1], 3);
- assert_eq!(v_d[2], 4);
- assert_eq!(v_d[3], 5);
- assert_eq!(v_d[4], 6);
-}
-
-#[test]
-fn test_slice_from() {
- let vec: &[_] = &[1, 2, 3, 4];
- assert_eq!(&vec[..], vec);
- let b: &[_] = &[3, 4];
- assert_eq!(&vec[2..], b);
- let b: &[_] = &[];
- assert_eq!(&vec[4..], b);
-}
-
-#[test]
-fn test_slice_to() {
- let vec: &[_] = &[1, 2, 3, 4];
- assert_eq!(&vec[..4], vec);
- let b: &[_] = &[1, 2];
- assert_eq!(&vec[..2], b);
- let b: &[_] = &[];
- assert_eq!(&vec[..0], b);
-}
-
-
-#[test]
-fn test_pop() {
- let mut v = vec![5];
- let e = v.pop();
- assert_eq!(v.len(), 0);
- assert_eq!(e, Some(5));
- let f = v.pop();
- assert_eq!(f, None);
- let g = v.pop();
- assert_eq!(g, None);
-}
-
-#[test]
-fn test_swap_remove() {
- let mut v = vec![1, 2, 3, 4, 5];
- let mut e = v.swap_remove(0);
- assert_eq!(e, 1);
- assert_eq!(v, [5, 2, 3, 4]);
- e = v.swap_remove(3);
- assert_eq!(e, 4);
- assert_eq!(v, [5, 2, 3]);
-}
-
-#[test]
-#[should_panic]
-fn test_swap_remove_fail() {
- let mut v = vec![1];
- let _ = v.swap_remove(0);
- let _ = v.swap_remove(0);
-}
-
-#[test]
-fn test_swap_remove_noncopyable() {
- // Tests that we don't accidentally run destructors twice.
- let mut v: Vec<Box<_>> = Vec::new();
- v.push(box 0);
- v.push(box 0);
- v.push(box 0);
- let mut _e = v.swap_remove(0);
- assert_eq!(v.len(), 2);
- _e = v.swap_remove(1);
- assert_eq!(v.len(), 1);
- _e = v.swap_remove(0);
- assert_eq!(v.len(), 0);
-}
-
-#[test]
-fn test_push() {
- // Test on-stack push().
- let mut v = vec![];
- v.push(1);
- assert_eq!(v.len(), 1);
- assert_eq!(v[0], 1);
-
- // Test on-heap push().
- v.push(2);
- assert_eq!(v.len(), 2);
- assert_eq!(v[0], 1);
- assert_eq!(v[1], 2);
-}
-
-#[test]
-fn test_truncate() {
- let mut v: Vec<Box<_>> = vec![box 6, box 5, box 4];
- v.truncate(1);
- let v = v;
- assert_eq!(v.len(), 1);
- assert_eq!(*(v[0]), 6);
- // If the unsafe block didn't drop things properly, we blow up here.
-}
-
-#[test]
-fn test_clear() {
- let mut v: Vec<Box<_>> = vec![box 6, box 5, box 4];
- v.clear();
- assert_eq!(v.len(), 0);
- // If the unsafe block didn't drop things properly, we blow up here.
-}
-
-#[test]
-fn test_retain() {
- let mut v = vec![1, 2, 3, 4, 5];
- v.retain(is_odd);
- assert_eq!(v, [1, 3, 5]);
-}
-
-#[test]
-fn test_binary_search() {
- assert_eq!([1, 2, 3, 4, 5].binary_search(&5).ok(), Some(4));
- assert_eq!([1, 2, 3, 4, 5].binary_search(&4).ok(), Some(3));
- assert_eq!([1, 2, 3, 4, 5].binary_search(&3).ok(), Some(2));
- assert_eq!([1, 2, 3, 4, 5].binary_search(&2).ok(), Some(1));
- assert_eq!([1, 2, 3, 4, 5].binary_search(&1).ok(), Some(0));
-
- assert_eq!([2, 4, 6, 8, 10].binary_search(&1).ok(), None);
- assert_eq!([2, 4, 6, 8, 10].binary_search(&5).ok(), None);
- assert_eq!([2, 4, 6, 8, 10].binary_search(&4).ok(), Some(1));
- assert_eq!([2, 4, 6, 8, 10].binary_search(&10).ok(), Some(4));
-
- assert_eq!([2, 4, 6, 8].binary_search(&1).ok(), None);
- assert_eq!([2, 4, 6, 8].binary_search(&5).ok(), None);
- assert_eq!([2, 4, 6, 8].binary_search(&4).ok(), Some(1));
- assert_eq!([2, 4, 6, 8].binary_search(&8).ok(), Some(3));
-
- assert_eq!([2, 4, 6].binary_search(&1).ok(), None);
- assert_eq!([2, 4, 6].binary_search(&5).ok(), None);
- assert_eq!([2, 4, 6].binary_search(&4).ok(), Some(1));
- assert_eq!([2, 4, 6].binary_search(&6).ok(), Some(2));
-
- assert_eq!([2, 4].binary_search(&1).ok(), None);
- assert_eq!([2, 4].binary_search(&5).ok(), None);
- assert_eq!([2, 4].binary_search(&2).ok(), Some(0));
- assert_eq!([2, 4].binary_search(&4).ok(), Some(1));
-
- assert_eq!([2].binary_search(&1).ok(), None);
- assert_eq!([2].binary_search(&5).ok(), None);
- assert_eq!([2].binary_search(&2).ok(), Some(0));
-
- assert_eq!([].binary_search(&1).ok(), None);
- assert_eq!([].binary_search(&5).ok(), None);
-
- assert!([1, 1, 1, 1, 1].binary_search(&1).ok() != None);
- assert!([1, 1, 1, 1, 2].binary_search(&1).ok() != None);
- assert!([1, 1, 1, 2, 2].binary_search(&1).ok() != None);
- assert!([1, 1, 2, 2, 2].binary_search(&1).ok() != None);
- assert_eq!([1, 2, 2, 2, 2].binary_search(&1).ok(), Some(0));
-
- assert_eq!([1, 2, 3, 4, 5].binary_search(&6).ok(), None);
- assert_eq!([1, 2, 3, 4, 5].binary_search(&0).ok(), None);
-}
-
-#[test]
-fn test_reverse() {
- let mut v = vec![10, 20];
- assert_eq!(v[0], 10);
- assert_eq!(v[1], 20);
- v.reverse();
- assert_eq!(v[0], 20);
- assert_eq!(v[1], 10);
-
- let mut v3 = Vec::<i32>::new();
- v3.reverse();
- assert!(v3.is_empty());
-}
-
-#[test]
-fn test_sort() {
- let mut rng = thread_rng();
-
- for len in (2..25).chain(500..510) {
- for _ in 0..100 {
- let mut v: Vec<_> = rng.gen_iter::<i32>().take(len).collect();
- let mut v1 = v.clone();
-
- v.sort();
- assert!(v.windows(2).all(|w| w[0] <= w[1]));
-
- v1.sort_by(|a, b| a.cmp(b));
- assert!(v1.windows(2).all(|w| w[0] <= w[1]));
-
- v1.sort_by(|a, b| b.cmp(a));
- assert!(v1.windows(2).all(|w| w[0] >= w[1]));
- }
- }
-
- // Sort using a completely random comparison function.
- // This will reorder the elements *somehow*, but won't panic.
- let mut v = [0; 500];
- for i in 0..v.len() {
- v[i] = i as i32;
- }
- v.sort_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap());
- v.sort();
- for i in 0..v.len() {
- assert_eq!(v[i], i as i32);
- }
-
- // Should not panic.
- [0i32; 0].sort();
- [(); 10].sort();
- [(); 100].sort();
-
- let mut v = [0xDEADBEEFu64];
- v.sort();
- assert!(v == [0xDEADBEEF]);
-}
-
-#[test]
-fn test_sort_stability() {
- for len in (2..25).chain(500..510) {
- for _ in 0..10 {
- let mut counts = [0; 10];
-
- // create a vector like [(6, 1), (5, 1), (6, 2), ...],
- // where the first item of each tuple is random, but
- // the second item represents which occurrence of that
- // number this element is, i.e. the second elements
- // will occur in sorted order.
- let mut v: Vec<_> = (0..len)
- .map(|_| {
- let n = thread_rng().gen::<usize>() % 10;
- counts[n] += 1;
- (n, counts[n])
- })
- .collect();
-
- // only sort on the first element, so an unstable sort
- // may mix up the counts.
- v.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
-
- // this comparison includes the count (the second item
- // of the tuple), so elements with equal first items
- // will need to be ordered with increasing
- // counts... i.e. exactly asserting that this sort is
- // stable.
- assert!(v.windows(2).all(|w| w[0] <= w[1]));
- }
- }
-}
-
-#[test]
-fn test_concat() {
- let v: [Vec<i32>; 0] = [];
- let c = v.concat();
- assert_eq!(c, []);
- let d = [vec![1], vec![2, 3]].concat();
- assert_eq!(d, [1, 2, 3]);
-
- let v: &[&[_]] = &[&[1], &[2, 3]];
- assert_eq!(v.join(&0), [1, 0, 2, 3]);
- let v: &[&[_]] = &[&[1], &[2], &[3]];
- assert_eq!(v.join(&0), [1, 0, 2, 0, 3]);
-}
-
-#[test]
-fn test_join() {
- let v: [Vec<i32>; 0] = [];
- assert_eq!(v.join(&0), []);
- assert_eq!([vec![1], vec![2, 3]].join(&0), [1, 0, 2, 3]);
- assert_eq!([vec![1], vec![2], vec![3]].join(&0), [1, 0, 2, 0, 3]);
-
- let v: [&[_]; 2] = [&[1], &[2, 3]];
- assert_eq!(v.join(&0), [1, 0, 2, 3]);
- let v: [&[_]; 3] = [&[1], &[2], &[3]];
- assert_eq!(v.join(&0), [1, 0, 2, 0, 3]);
-}
-
-#[test]
-fn test_insert() {
- let mut a = vec![1, 2, 4];
- a.insert(2, 3);
- assert_eq!(a, [1, 2, 3, 4]);
-
- let mut a = vec![1, 2, 3];
- a.insert(0, 0);
- assert_eq!(a, [0, 1, 2, 3]);
-
- let mut a = vec![1, 2, 3];
- a.insert(3, 4);
- assert_eq!(a, [1, 2, 3, 4]);
-
- let mut a = vec![];
- a.insert(0, 1);
- assert_eq!(a, [1]);
-}
-
-#[test]
-#[should_panic]
-fn test_insert_oob() {
- let mut a = vec![1, 2, 3];
- a.insert(4, 5);
-}
-
-#[test]
-fn test_remove() {
- let mut a = vec![1, 2, 3, 4];
-
- assert_eq!(a.remove(2), 3);
- assert_eq!(a, [1, 2, 4]);
-
- assert_eq!(a.remove(2), 4);
- assert_eq!(a, [1, 2]);
-
- assert_eq!(a.remove(0), 1);
- assert_eq!(a, [2]);
-
- assert_eq!(a.remove(0), 2);
- assert_eq!(a, []);
-}
-
-#[test]
-#[should_panic]
-fn test_remove_fail() {
- let mut a = vec![1];
- let _ = a.remove(0);
- let _ = a.remove(0);
-}
-
-#[test]
-fn test_capacity() {
- let mut v = vec![0];
- v.reserve_exact(10);
- assert!(v.capacity() >= 11);
-}
-
-#[test]
-fn test_slice_2() {
- let v = vec![1, 2, 3, 4, 5];
- let v = &v[1..3];
- assert_eq!(v.len(), 2);
- assert_eq!(v[0], 2);
- assert_eq!(v[1], 3);
-}
-
-macro_rules! assert_order {
- (Greater, $a:expr, $b:expr) => {
- assert_eq!($a.cmp($b), Greater);
- assert!($a > $b);
- };
- (Less, $a:expr, $b:expr) => {
- assert_eq!($a.cmp($b), Less);
- assert!($a < $b);
- };
- (Equal, $a:expr, $b:expr) => {
- assert_eq!($a.cmp($b), Equal);
- assert_eq!($a, $b);
- }
-}
-
-#[test]
-fn test_total_ord_u8() {
- let c = &[1u8, 2, 3];
- assert_order!(Greater, &[1u8, 2, 3, 4][..], &c[..]);
- let c = &[1u8, 2, 3, 4];
- assert_order!(Less, &[1u8, 2, 3][..], &c[..]);
- let c = &[1u8, 2, 3, 6];
- assert_order!(Equal, &[1u8, 2, 3, 6][..], &c[..]);
- let c = &[1u8, 2, 3, 4, 5, 6];
- assert_order!(Less, &[1u8, 2, 3, 4, 5, 5, 5, 5][..], &c[..]);
- let c = &[1u8, 2, 3, 4];
- assert_order!(Greater, &[2u8, 2][..], &c[..]);
-}
-
-
-#[test]
-fn test_total_ord_i32() {
- let c = &[1, 2, 3];
- assert_order!(Greater, &[1, 2, 3, 4][..], &c[..]);
- let c = &[1, 2, 3, 4];
- assert_order!(Less, &[1, 2, 3][..], &c[..]);
- let c = &[1, 2, 3, 6];
- assert_order!(Equal, &[1, 2, 3, 6][..], &c[..]);
- let c = &[1, 2, 3, 4, 5, 6];
- assert_order!(Less, &[1, 2, 3, 4, 5, 5, 5, 5][..], &c[..]);
- let c = &[1, 2, 3, 4];
- assert_order!(Greater, &[2, 2][..], &c[..]);
-}
-
-#[test]
-fn test_iterator() {
- let xs = [1, 2, 5, 10, 11];
- let mut it = xs.iter();
- assert_eq!(it.size_hint(), (5, Some(5)));
- assert_eq!(it.next().unwrap(), &1);
- assert_eq!(it.size_hint(), (4, Some(4)));
- assert_eq!(it.next().unwrap(), &2);
- assert_eq!(it.size_hint(), (3, Some(3)));
- assert_eq!(it.next().unwrap(), &5);
- assert_eq!(it.size_hint(), (2, Some(2)));
- assert_eq!(it.next().unwrap(), &10);
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(it.next().unwrap(), &11);
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert!(it.next().is_none());
-}
-
-#[test]
-fn test_iter_size_hints() {
- let mut xs = [1, 2, 5, 10, 11];
- assert_eq!(xs.iter().size_hint(), (5, Some(5)));
- assert_eq!(xs.iter_mut().size_hint(), (5, Some(5)));
-}
-
-#[test]
-fn test_iter_as_slice() {
- let xs = [1, 2, 5, 10, 11];
- let mut iter = xs.iter();
- assert_eq!(iter.as_slice(), &[1, 2, 5, 10, 11]);
- iter.next();
- assert_eq!(iter.as_slice(), &[2, 5, 10, 11]);
-}
-
-#[test]
-fn test_iter_as_ref() {
- let xs = [1, 2, 5, 10, 11];
- let mut iter = xs.iter();
- assert_eq!(iter.as_ref(), &[1, 2, 5, 10, 11]);
- iter.next();
- assert_eq!(iter.as_ref(), &[2, 5, 10, 11]);
-}
-
-#[test]
-fn test_iter_clone() {
- let xs = [1, 2, 5];
- let mut it = xs.iter();
- it.next();
- let mut jt = it.clone();
- assert_eq!(it.next(), jt.next());
- assert_eq!(it.next(), jt.next());
- assert_eq!(it.next(), jt.next());
-}
-
-#[test]
-fn test_iter_is_empty() {
- let xs = [1, 2, 5, 10, 11];
- for i in 0..xs.len() {
- for j in i..xs.len() {
- assert_eq!(xs[i..j].iter().is_empty(), xs[i..j].is_empty());
- }
- }
-}
-
-#[test]
-fn test_mut_iterator() {
- let mut xs = [1, 2, 3, 4, 5];
- for x in &mut xs {
- *x += 1;
- }
- assert!(xs == [2, 3, 4, 5, 6])
-}
-
-#[test]
-fn test_rev_iterator() {
-
- let xs = [1, 2, 5, 10, 11];
- let ys = [11, 10, 5, 2, 1];
- let mut i = 0;
- for &x in xs.iter().rev() {
- assert_eq!(x, ys[i]);
- i += 1;
- }
- assert_eq!(i, 5);
-}
-
-#[test]
-fn test_mut_rev_iterator() {
- let mut xs = [1, 2, 3, 4, 5];
- for (i, x) in xs.iter_mut().rev().enumerate() {
- *x += i;
- }
- assert!(xs == [5, 5, 5, 5, 5])
-}
-
-#[test]
-fn test_move_iterator() {
- let xs = vec![1, 2, 3, 4, 5];
- assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10 * a + b),
- 12345);
-}
-
-#[test]
-fn test_move_rev_iterator() {
- let xs = vec![1, 2, 3, 4, 5];
- assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10 * a + b),
- 54321);
-}
-
-#[test]
-fn test_splitator() {
- let xs = &[1, 2, 3, 4, 5];
-
- let splits: &[&[_]] = &[&[1], &[3], &[5]];
- assert_eq!(xs.split(|x| *x % 2 == 0).collect::<Vec<_>>(), splits);
- let splits: &[&[_]] = &[&[], &[2, 3, 4, 5]];
- assert_eq!(xs.split(|x| *x == 1).collect::<Vec<_>>(), splits);
- let splits: &[&[_]] = &[&[1, 2, 3, 4], &[]];
- assert_eq!(xs.split(|x| *x == 5).collect::<Vec<_>>(), splits);
- let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
- assert_eq!(xs.split(|x| *x == 10).collect::<Vec<_>>(), splits);
- let splits: &[&[_]] = &[&[], &[], &[], &[], &[], &[]];
- assert_eq!(xs.split(|_| true).collect::<Vec<&[i32]>>(), splits);
-
- let xs: &[i32] = &[];
- let splits: &[&[i32]] = &[&[]];
- assert_eq!(xs.split(|x| *x == 5).collect::<Vec<&[i32]>>(), splits);
-}
-
-#[test]
-fn test_splitnator() {
- let xs = &[1, 2, 3, 4, 5];
-
- let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
- assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(), splits);
- let splits: &[&[_]] = &[&[1], &[3, 4, 5]];
- assert_eq!(xs.splitn(2, |x| *x % 2 == 0).collect::<Vec<_>>(), splits);
- let splits: &[&[_]] = &[&[], &[], &[], &[4, 5]];
- assert_eq!(xs.splitn(4, |_| true).collect::<Vec<_>>(), splits);
-
- let xs: &[i32] = &[];
- let splits: &[&[i32]] = &[&[]];
- assert_eq!(xs.splitn(2, |x| *x == 5).collect::<Vec<_>>(), splits);
-}
-
-#[test]
-fn test_splitnator_mut() {
- let xs = &mut [1, 2, 3, 4, 5];
-
- let splits: &[&mut [_]] = &[&mut [1, 2, 3, 4, 5]];
- assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
- splits);
- let splits: &[&mut [_]] = &[&mut [1], &mut [3, 4, 5]];
- assert_eq!(xs.splitn_mut(2, |x| *x % 2 == 0).collect::<Vec<_>>(),
- splits);
- let splits: &[&mut [_]] = &[&mut [], &mut [], &mut [], &mut [4, 5]];
- assert_eq!(xs.splitn_mut(4, |_| true).collect::<Vec<_>>(), splits);
-
- let xs: &mut [i32] = &mut [];
- let splits: &[&mut [i32]] = &[&mut []];
- assert_eq!(xs.splitn_mut(2, |x| *x == 5).collect::<Vec<_>>(), splits);
-}
-
-#[test]
-fn test_rsplitator() {
- let xs = &[1, 2, 3, 4, 5];
-
- let splits: &[&[_]] = &[&[5], &[3], &[1]];
- assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits);
- let splits: &[&[_]] = &[&[2, 3, 4, 5], &[]];
- assert_eq!(xs.split(|x| *x == 1).rev().collect::<Vec<_>>(), splits);
- let splits: &[&[_]] = &[&[], &[1, 2, 3, 4]];
- assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
- let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
- assert_eq!(xs.split(|x| *x == 10).rev().collect::<Vec<_>>(), splits);
-
- let xs: &[i32] = &[];
- let splits: &[&[i32]] = &[&[]];
- assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<&[i32]>>(), splits);
-}
-
-#[test]
-fn test_rsplitnator() {
- let xs = &[1, 2, 3, 4, 5];
-
- let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
- assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(), splits);
- let splits: &[&[_]] = &[&[5], &[1, 2, 3]];
- assert_eq!(xs.rsplitn(2, |x| *x % 2 == 0).collect::<Vec<_>>(), splits);
- let splits: &[&[_]] = &[&[], &[], &[], &[1, 2]];
- assert_eq!(xs.rsplitn(4, |_| true).collect::<Vec<_>>(), splits);
-
- let xs: &[i32] = &[];
- let splits: &[&[i32]] = &[&[]];
- assert_eq!(xs.rsplitn(2, |x| *x == 5).collect::<Vec<&[i32]>>(), splits);
- assert!(xs.rsplitn(0, |x| *x % 2 == 0).next().is_none());
-}
-
-#[test]
-fn test_windowsator() {
- let v = &[1, 2, 3, 4];
-
- let wins: &[&[_]] = &[&[1, 2], &[2, 3], &[3, 4]];
- assert_eq!(v.windows(2).collect::<Vec<_>>(), wins);
-
- let wins: &[&[_]] = &[&[1, 2, 3], &[2, 3, 4]];
- assert_eq!(v.windows(3).collect::<Vec<_>>(), wins);
- assert!(v.windows(6).next().is_none());
-
- let wins: &[&[_]] = &[&[3, 4], &[2, 3], &[1, 2]];
- assert_eq!(v.windows(2).rev().collect::<Vec<&[_]>>(), wins);
-}
-
-#[test]
-#[should_panic]
-fn test_windowsator_0() {
- let v = &[1, 2, 3, 4];
- let _it = v.windows(0);
-}
-
-#[test]
-fn test_chunksator() {
- let v = &[1, 2, 3, 4, 5];
-
- assert_eq!(v.chunks(2).len(), 3);
-
- let chunks: &[&[_]] = &[&[1, 2], &[3, 4], &[5]];
- assert_eq!(v.chunks(2).collect::<Vec<_>>(), chunks);
- let chunks: &[&[_]] = &[&[1, 2, 3], &[4, 5]];
- assert_eq!(v.chunks(3).collect::<Vec<_>>(), chunks);
- let chunks: &[&[_]] = &[&[1, 2, 3, 4, 5]];
- assert_eq!(v.chunks(6).collect::<Vec<_>>(), chunks);
-
- let chunks: &[&[_]] = &[&[5], &[3, 4], &[1, 2]];
- assert_eq!(v.chunks(2).rev().collect::<Vec<_>>(), chunks);
-}
-
-#[test]
-#[should_panic]
-fn test_chunksator_0() {
- let v = &[1, 2, 3, 4];
- let _it = v.chunks(0);
-}
-
-#[test]
-fn test_reverse_part() {
- let mut values = [1, 2, 3, 4, 5];
- values[1..4].reverse();
- assert!(values == [1, 4, 3, 2, 5]);
-}
-
-#[test]
-fn test_show() {
- macro_rules! test_show_vec {
- ($x:expr, $x_str:expr) => ({
- let (x, x_str) = ($x, $x_str);
- assert_eq!(format!("{:?}", x), x_str);
- assert_eq!(format!("{:?}", x), x_str);
- })
- }
- let empty = Vec::<i32>::new();
- test_show_vec!(empty, "[]");
- test_show_vec!(vec![1], "[1]");
- test_show_vec!(vec![1, 2, 3], "[1, 2, 3]");
- test_show_vec!(vec![vec![], vec![1], vec![1, 1]], "[[], [1], [1, 1]]");
-
- let empty_mut: &mut [i32] = &mut [];
- test_show_vec!(empty_mut, "[]");
- let v = &mut [1];
- test_show_vec!(v, "[1]");
- let v = &mut [1, 2, 3];
- test_show_vec!(v, "[1, 2, 3]");
- let v: &mut [&mut [_]] = &mut [&mut [], &mut [1], &mut [1, 1]];
- test_show_vec!(v, "[[], [1], [1, 1]]");
-}
-
-#[test]
-fn test_vec_default() {
- macro_rules! t {
- ($ty:ty) => {{
- let v: $ty = Default::default();
- assert!(v.is_empty());
- }}
- }
-
- t!(&[i32]);
- t!(Vec<i32>);
-}
-
-#[test]
-#[should_panic]
-fn test_overflow_does_not_cause_segfault() {
- let mut v = vec![];
- v.reserve_exact(!0);
- v.push(1);
- v.push(2);
-}
-
-#[test]
-#[should_panic]
-fn test_overflow_does_not_cause_segfault_managed() {
- let mut v = vec![Rc::new(1)];
- v.reserve_exact(!0);
- v.push(Rc::new(2));
-}
-
-#[test]
-fn test_mut_split_at() {
- let mut values = [1, 2, 3, 4, 5];
- {
- let (left, right) = values.split_at_mut(2);
- {
- let left: &[_] = left;
- assert!(left[..left.len()] == [1, 2]);
- }
- for p in left {
- *p += 1;
- }
-
- {
- let right: &[_] = right;
- assert!(right[..right.len()] == [3, 4, 5]);
- }
- for p in right {
- *p += 2;
- }
- }
-
- assert!(values == [2, 3, 5, 6, 7]);
-}
-
-#[derive(Clone, PartialEq)]
-struct Foo;
-
-#[test]
-fn test_iter_zero_sized() {
- let mut v = vec![Foo, Foo, Foo];
- assert_eq!(v.len(), 3);
- let mut cnt = 0;
-
- for f in &v {
- assert!(*f == Foo);
- cnt += 1;
- }
- assert_eq!(cnt, 3);
-
- for f in &v[1..3] {
- assert!(*f == Foo);
- cnt += 1;
- }
- assert_eq!(cnt, 5);
-
- for f in &mut v {
- assert!(*f == Foo);
- cnt += 1;
- }
- assert_eq!(cnt, 8);
-
- for f in v {
- assert!(f == Foo);
- cnt += 1;
- }
- assert_eq!(cnt, 11);
-
- let xs: [Foo; 3] = [Foo, Foo, Foo];
- cnt = 0;
- for f in &xs {
- assert!(*f == Foo);
- cnt += 1;
- }
- assert!(cnt == 3);
-}
-
-#[test]
-fn test_shrink_to_fit() {
- let mut xs = vec![0, 1, 2, 3];
- for i in 4..100 {
- xs.push(i)
- }
- assert_eq!(xs.capacity(), 128);
- xs.shrink_to_fit();
- assert_eq!(xs.capacity(), 100);
- assert_eq!(xs, (0..100).collect::<Vec<_>>());
-}
-
-#[test]
-fn test_starts_with() {
- assert!(b"foobar".starts_with(b"foo"));
- assert!(!b"foobar".starts_with(b"oob"));
- assert!(!b"foobar".starts_with(b"bar"));
- assert!(!b"foo".starts_with(b"foobar"));
- assert!(!b"bar".starts_with(b"foobar"));
- assert!(b"foobar".starts_with(b"foobar"));
- let empty: &[u8] = &[];
- assert!(empty.starts_with(empty));
- assert!(!empty.starts_with(b"foo"));
- assert!(b"foobar".starts_with(empty));
-}
-
-#[test]
-fn test_ends_with() {
- assert!(b"foobar".ends_with(b"bar"));
- assert!(!b"foobar".ends_with(b"oba"));
- assert!(!b"foobar".ends_with(b"foo"));
- assert!(!b"foo".ends_with(b"foobar"));
- assert!(!b"bar".ends_with(b"foobar"));
- assert!(b"foobar".ends_with(b"foobar"));
- let empty: &[u8] = &[];
- assert!(empty.ends_with(empty));
- assert!(!empty.ends_with(b"foo"));
- assert!(b"foobar".ends_with(empty));
-}
-
-#[test]
-fn test_mut_splitator() {
- let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0];
- assert_eq!(xs.split_mut(|x| *x == 0).count(), 6);
- for slice in xs.split_mut(|x| *x == 0) {
- slice.reverse();
- }
- assert!(xs == [0, 1, 0, 3, 2, 0, 0, 5, 4, 0]);
-
- let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0, 6, 7];
- for slice in xs.split_mut(|x| *x == 0).take(5) {
- slice.reverse();
- }
- assert!(xs == [0, 1, 0, 3, 2, 0, 0, 5, 4, 0, 6, 7]);
-}
-
-#[test]
-fn test_mut_splitator_rev() {
- let mut xs = [1, 2, 0, 3, 4, 0, 0, 5, 6, 0];
- for slice in xs.split_mut(|x| *x == 0).rev().take(4) {
- slice.reverse();
- }
- assert!(xs == [1, 2, 0, 4, 3, 0, 0, 6, 5, 0]);
-}
-
-#[test]
-fn test_get_mut() {
- let mut v = [0, 1, 2];
- assert_eq!(v.get_mut(3), None);
- v.get_mut(1).map(|e| *e = 7);
- assert_eq!(v[1], 7);
- let mut x = 2;
- assert_eq!(v.get_mut(2), Some(&mut x));
-}
-
-#[test]
-fn test_mut_chunks() {
- let mut v = [0, 1, 2, 3, 4, 5, 6];
- assert_eq!(v.chunks_mut(2).len(), 4);
- for (i, chunk) in v.chunks_mut(3).enumerate() {
- for x in chunk {
- *x = i as u8;
- }
- }
- let result = [0, 0, 0, 1, 1, 1, 2];
- assert!(v == result);
-}
-
-#[test]
-fn test_mut_chunks_rev() {
- let mut v = [0, 1, 2, 3, 4, 5, 6];
- for (i, chunk) in v.chunks_mut(3).rev().enumerate() {
- for x in chunk {
- *x = i as u8;
- }
- }
- let result = [2, 2, 2, 1, 1, 1, 0];
- assert!(v == result);
-}
-
-#[test]
-#[should_panic]
-fn test_mut_chunks_0() {
- let mut v = [1, 2, 3, 4];
- let _it = v.chunks_mut(0);
-}
-
-#[test]
-fn test_mut_last() {
- let mut x = [1, 2, 3, 4, 5];
- let h = x.last_mut();
- assert_eq!(*h.unwrap(), 5);
-
- let y: &mut [i32] = &mut [];
- assert!(y.last_mut().is_none());
-}
-
-#[test]
-fn test_to_vec() {
- let xs: Box<_> = box [1, 2, 3];
- let ys = xs.to_vec();
- assert_eq!(ys, [1, 2, 3]);
-}
-
-#[test]
-fn test_box_slice_clone() {
- let data = vec![vec![0, 1], vec![0], vec![1]];
- let data2 = data.clone().into_boxed_slice().clone().to_vec();
-
- assert_eq!(data, data2);
-}
-
-#[test]
-#[cfg_attr(target_os = "emscripten", ignore)]
-fn test_box_slice_clone_panics() {
- use std::sync::Arc;
- use std::sync::atomic::{AtomicUsize, Ordering};
- use std::thread::spawn;
-
- struct Canary {
- count: Arc<AtomicUsize>,
- panics: bool,
- }
-
- impl Drop for Canary {
- fn drop(&mut self) {
- self.count.fetch_add(1, Ordering::SeqCst);
- }
- }
-
- impl Clone for Canary {
- fn clone(&self) -> Self {
- if self.panics {
- panic!()
- }
-
- Canary {
- count: self.count.clone(),
- panics: self.panics,
- }
- }
- }
-
- let drop_count = Arc::new(AtomicUsize::new(0));
- let canary = Canary {
- count: drop_count.clone(),
- panics: false,
- };
- let panic = Canary {
- count: drop_count.clone(),
- panics: true,
- };
-
- spawn(move || {
- // When xs is dropped, +5.
- let xs = vec![canary.clone(), canary.clone(), canary.clone(), panic, canary]
- .into_boxed_slice();
-
- // When panic is cloned, +3.
- xs.clone();
- })
- .join()
- .unwrap_err();
-
- // Total = 8
- assert_eq!(drop_count.load(Ordering::SeqCst), 8);
-}
-
-#[test]
-fn test_copy_from_slice() {
- let src = [0, 1, 2, 3, 4, 5];
- let mut dst = [0; 6];
- dst.copy_from_slice(&src);
- assert_eq!(src, dst)
-}
-
-#[test]
-#[should_panic(expected = "destination and source slices have different lengths")]
-fn test_copy_from_slice_dst_longer() {
- let src = [0, 1, 2, 3];
- let mut dst = [0; 5];
- dst.copy_from_slice(&src);
-}
-
-#[test]
-#[should_panic(expected = "destination and source slices have different lengths")]
-fn test_copy_from_slice_dst_shorter() {
- let src = [0, 1, 2, 3];
- let mut dst = [0; 3];
- dst.copy_from_slice(&src);
-}
+++ /dev/null
-// 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.
-
-use std::borrow::Cow;
-use std::cmp::Ordering::{Equal, Greater, Less};
-use std::str::from_utf8;
-
-#[test]
-fn test_le() {
- assert!("" <= "");
- assert!("" <= "foo");
- assert!("foo" <= "foo");
- assert!("foo" != "bar");
-}
-
-#[test]
-fn test_find() {
- assert_eq!("hello".find('l'), Some(2));
- assert_eq!("hello".find(|c:char| c == 'o'), Some(4));
- assert!("hello".find('x').is_none());
- assert!("hello".find(|c:char| c == 'x').is_none());
- assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
- assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
-}
-
-#[test]
-fn test_rfind() {
- assert_eq!("hello".rfind('l'), Some(3));
- assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4));
- assert!("hello".rfind('x').is_none());
- assert!("hello".rfind(|c:char| c == 'x').is_none());
- assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
- assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
-}
-
-#[test]
-fn test_collect() {
- let empty = "";
- let s: String = empty.chars().collect();
- assert_eq!(empty, s);
- let data = "ประเทศไทย中";
- let s: String = data.chars().collect();
- assert_eq!(data, s);
-}
-
-#[test]
-fn test_into_bytes() {
- let data = String::from("asdf");
- let buf = data.into_bytes();
- assert_eq!(buf, b"asdf");
-}
-
-#[test]
-fn test_find_str() {
- // byte positions
- assert_eq!("".find(""), Some(0));
- assert!("banana".find("apple pie").is_none());
-
- let data = "abcabc";
- assert_eq!(data[0..6].find("ab"), Some(0));
- assert_eq!(data[2..6].find("ab"), Some(3 - 2));
- assert!(data[2..4].find("ab").is_none());
-
- let string = "ประเทศไทย中华Việt Nam";
- let mut data = String::from(string);
- data.push_str(string);
- assert!(data.find("ไท华").is_none());
- assert_eq!(data[0..43].find(""), Some(0));
- assert_eq!(data[6..43].find(""), Some(6 - 6));
-
- assert_eq!(data[0..43].find("ประ"), Some( 0));
- assert_eq!(data[0..43].find("ทศไ"), Some(12));
- assert_eq!(data[0..43].find("ย中"), Some(24));
- assert_eq!(data[0..43].find("iệt"), Some(34));
- assert_eq!(data[0..43].find("Nam"), Some(40));
-
- assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
- assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
- assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
- assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
- assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
-
- // find every substring -- assert that it finds it, or an earlier occurrence.
- let string = "Việt Namacbaabcaabaaba";
- for (i, ci) in string.char_indices() {
- let ip = i + ci.len_utf8();
- for j in string[ip..].char_indices()
- .map(|(i, _)| i)
- .chain(Some(string.len() - ip))
- {
- let pat = &string[i..ip + j];
- assert!(match string.find(pat) {
- None => false,
- Some(x) => x <= i,
- });
- assert!(match string.rfind(pat) {
- None => false,
- Some(x) => x >= i,
- });
- }
- }
-}
-
-fn s(x: &str) -> String { x.to_string() }
-
-macro_rules! test_concat {
- ($expected: expr, $string: expr) => {
- {
- let s: String = $string.concat();
- assert_eq!($expected, s);
- }
- }
-}
-
-#[test]
-fn test_concat_for_different_types() {
- test_concat!("ab", vec![s("a"), s("b")]);
- test_concat!("ab", vec!["a", "b"]);
-}
-
-#[test]
-fn test_concat_for_different_lengths() {
- let empty: &[&str] = &[];
- test_concat!("", empty);
- test_concat!("a", ["a"]);
- test_concat!("ab", ["a", "b"]);
- test_concat!("abc", ["", "a", "bc"]);
-}
-
-macro_rules! test_join {
- ($expected: expr, $string: expr, $delim: expr) => {
- {
- let s = $string.join($delim);
- assert_eq!($expected, s);
- }
- }
-}
-
-#[test]
-fn test_join_for_different_types() {
- test_join!("a-b", ["a", "b"], "-");
- let hyphen = "-".to_string();
- test_join!("a-b", [s("a"), s("b")], &*hyphen);
- test_join!("a-b", vec!["a", "b"], &*hyphen);
- test_join!("a-b", &*vec!["a", "b"], "-");
- test_join!("a-b", vec![s("a"), s("b")], "-");
-}
-
-#[test]
-fn test_join_for_different_lengths() {
- let empty: &[&str] = &[];
- test_join!("", empty, "-");
- test_join!("a", ["a"], "-");
- test_join!("a-b", ["a", "b"], "-");
- test_join!("-a-bc", ["", "a", "bc"], "-");
-}
-
-#[test]
-fn test_unsafe_slice() {
- assert_eq!("ab", unsafe {"abc".slice_unchecked(0, 2)});
- assert_eq!("bc", unsafe {"abc".slice_unchecked(1, 3)});
- assert_eq!("", unsafe {"abc".slice_unchecked(1, 1)});
- fn a_million_letter_a() -> String {
- let mut i = 0;
- let mut rs = String::new();
- while i < 100000 {
- rs.push_str("aaaaaaaaaa");
- i += 1;
- }
- rs
- }
- fn half_a_million_letter_a() -> String {
- let mut i = 0;
- let mut rs = String::new();
- while i < 100000 {
- rs.push_str("aaaaa");
- i += 1;
- }
- rs
- }
- let letters = a_million_letter_a();
- assert_eq!(half_a_million_letter_a(),
- unsafe { letters.slice_unchecked(0, 500000)});
-}
-
-#[test]
-fn test_starts_with() {
- assert!("".starts_with(""));
- assert!("abc".starts_with(""));
- assert!("abc".starts_with("a"));
- assert!(!"a".starts_with("abc"));
- assert!(!"".starts_with("abc"));
- assert!(!"ödd".starts_with("-"));
- assert!("ödd".starts_with("öd"));
-}
-
-#[test]
-fn test_ends_with() {
- assert!("".ends_with(""));
- assert!("abc".ends_with(""));
- assert!("abc".ends_with("c"));
- assert!(!"a".ends_with("abc"));
- assert!(!"".ends_with("abc"));
- assert!(!"ddö".ends_with("-"));
- assert!("ddö".ends_with("dö"));
-}
-
-#[test]
-fn test_is_empty() {
- assert!("".is_empty());
- assert!(!"a".is_empty());
-}
-
-#[test]
-fn test_replacen() {
- assert_eq!("".replacen('a', "b", 5), "");
- assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
- assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
-
- let test = "test";
- assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
- assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
- assert_eq!(" test test ".replacen(test, "", 5), " ");
-
- assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
-}
-
-#[test]
-fn test_replace() {
- let a = "a";
- assert_eq!("".replace(a, "b"), "");
- assert_eq!("a".replace(a, "b"), "b");
- assert_eq!("ab".replace(a, "b"), "bb");
- let test = "test";
- assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
- assert_eq!(" test test ".replace(test, ""), " ");
-}
-
-#[test]
-fn test_replace_2a() {
- let data = "ประเทศไทย中华";
- let repl = "دولة الكويت";
-
- let a = "ประเ";
- let a2 = "دولة الكويتทศไทย中华";
- assert_eq!(data.replace(a, repl), a2);
-}
-
-#[test]
-fn test_replace_2b() {
- let data = "ประเทศไทย中华";
- let repl = "دولة الكويت";
-
- let b = "ะเ";
- let b2 = "ปรدولة الكويتทศไทย中华";
- assert_eq!(data.replace(b, repl), b2);
-}
-
-#[test]
-fn test_replace_2c() {
- let data = "ประเทศไทย中华";
- let repl = "دولة الكويت";
-
- let c = "中华";
- let c2 = "ประเทศไทยدولة الكويت";
- assert_eq!(data.replace(c, repl), c2);
-}
-
-#[test]
-fn test_replace_2d() {
- let data = "ประเทศไทย中华";
- let repl = "دولة الكويت";
-
- let d = "ไท华";
- assert_eq!(data.replace(d, repl), data);
-}
-
-#[test]
-fn test_replace_pattern() {
- let data = "abcdαβγδabcdαβγδ";
- assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
- assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
- assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
- assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
-}
-
-#[test]
-fn test_slice() {
- assert_eq!("ab", &"abc"[0..2]);
- assert_eq!("bc", &"abc"[1..3]);
- assert_eq!("", &"abc"[1..1]);
- assert_eq!("\u{65e5}", &"\u{65e5}\u{672c}"[0..3]);
-
- let data = "ประเทศไทย中华";
- assert_eq!("ป", &data[0..3]);
- assert_eq!("ร", &data[3..6]);
- assert_eq!("", &data[3..3]);
- assert_eq!("华", &data[30..33]);
-
- fn a_million_letter_x() -> String {
- let mut i = 0;
- let mut rs = String::new();
- while i < 100000 {
- rs.push_str("华华华华华华华华华华");
- i += 1;
- }
- rs
- }
- fn half_a_million_letter_x() -> String {
- let mut i = 0;
- let mut rs = String::new();
- while i < 100000 {
- rs.push_str("华华华华华");
- i += 1;
- }
- rs
- }
- let letters = a_million_letter_x();
- assert_eq!(half_a_million_letter_x(), &letters[0..3 * 500000]);
-}
-
-#[test]
-fn test_slice_2() {
- let ss = "中华Việt Nam";
-
- assert_eq!("华", &ss[3..6]);
- assert_eq!("Việt Nam", &ss[6..16]);
-
- assert_eq!("ab", &"abc"[0..2]);
- assert_eq!("bc", &"abc"[1..3]);
- assert_eq!("", &"abc"[1..1]);
-
- assert_eq!("中", &ss[0..3]);
- assert_eq!("华V", &ss[3..7]);
- assert_eq!("", &ss[3..3]);
- /*0: 中
- 3: 华
- 6: V
- 7: i
- 8: ệ
- 11: t
- 12:
- 13: N
- 14: a
- 15: m */
-}
-
-#[test]
-#[should_panic]
-fn test_slice_fail() {
- &"中华Việt Nam"[0..2];
-}
-
-
-#[test]
-fn test_is_char_boundary() {
- let s = "ศไทย中华Việt Nam β-release 🐱123";
- assert!(s.is_char_boundary(0));
- assert!(s.is_char_boundary(s.len()));
- assert!(!s.is_char_boundary(s.len() + 1));
- for (i, ch) in s.char_indices() {
- // ensure character locations are boundaries and continuation bytes are not
- assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
- for j in 1..ch.len_utf8() {
- assert!(!s.is_char_boundary(i + j),
- "{} should not be a char boundary in {:?}", i + j, s);
- }
- }
-}
-const LOREM_PARAGRAPH: &'static str = "\
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
-ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
-eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
-sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
-tempus vel, gravida nec quam.";
-
-// check the panic includes the prefix of the sliced string
-#[test]
-#[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
-fn test_slice_fail_truncated_1() {
- &LOREM_PARAGRAPH[..1024];
-}
-// check the truncation in the panic message
-#[test]
-#[should_panic(expected="luctus, im`[...]")]
-fn test_slice_fail_truncated_2() {
- &LOREM_PARAGRAPH[..1024];
-}
-
-#[test]
-#[should_panic(expected="byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of")]
-fn test_slice_fail_boundary_1() {
- &"abcαβγ"[4..];
-}
-
-#[test]
-#[should_panic(expected="byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of")]
-fn test_slice_fail_boundary_2() {
- &"abcαβγ"[2..6];
-}
-
-#[test]
-fn test_slice_from() {
- assert_eq!(&"abcd"[0..], "abcd");
- assert_eq!(&"abcd"[2..], "cd");
- assert_eq!(&"abcd"[4..], "");
-}
-#[test]
-fn test_slice_to() {
- assert_eq!(&"abcd"[..0], "");
- assert_eq!(&"abcd"[..2], "ab");
- assert_eq!(&"abcd"[..4], "abcd");
-}
-
-#[test]
-fn test_trim_left_matches() {
- let v: &[char] = &[];
- assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** ");
- let chars: &[char] = &['*', ' '];
- assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** ");
- assert_eq!(" *** *** ".trim_left_matches(chars), "");
- assert_eq!("foo *** ".trim_left_matches(chars), "foo *** ");
-
- assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
- let chars: &[char] = &['1', '2'];
- assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12");
- assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123");
-}
-
-#[test]
-fn test_trim_right_matches() {
- let v: &[char] = &[];
- assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** ");
- let chars: &[char] = &['*', ' '];
- assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo");
- assert_eq!(" *** *** ".trim_right_matches(chars), "");
- assert_eq!(" *** foo".trim_right_matches(chars), " *** foo");
-
- assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
- let chars: &[char] = &['1', '2'];
- assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar");
- assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar");
-}
-
-#[test]
-fn test_trim_matches() {
- let v: &[char] = &[];
- assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
- let chars: &[char] = &['*', ' '];
- assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
- assert_eq!(" *** *** ".trim_matches(chars), "");
- assert_eq!("foo".trim_matches(chars), "foo");
-
- assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
- let chars: &[char] = &['1', '2'];
- assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
- assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
-}
-
-#[test]
-fn test_trim_left() {
- assert_eq!("".trim_left(), "");
- assert_eq!("a".trim_left(), "a");
- assert_eq!(" ".trim_left(), "");
- assert_eq!(" blah".trim_left(), "blah");
- assert_eq!(" \u{3000} wut".trim_left(), "wut");
- assert_eq!("hey ".trim_left(), "hey ");
-}
-
-#[test]
-fn test_trim_right() {
- assert_eq!("".trim_right(), "");
- assert_eq!("a".trim_right(), "a");
- assert_eq!(" ".trim_right(), "");
- assert_eq!("blah ".trim_right(), "blah");
- assert_eq!("wut \u{3000} ".trim_right(), "wut");
- assert_eq!(" hey".trim_right(), " hey");
-}
-
-#[test]
-fn test_trim() {
- assert_eq!("".trim(), "");
- assert_eq!("a".trim(), "a");
- assert_eq!(" ".trim(), "");
- assert_eq!(" blah ".trim(), "blah");
- assert_eq!("\nwut \u{3000} ".trim(), "wut");
- assert_eq!(" hey dude ".trim(), "hey dude");
-}
-
-#[test]
-fn test_is_whitespace() {
- assert!("".chars().all(|c| c.is_whitespace()));
- assert!(" ".chars().all(|c| c.is_whitespace()));
- assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
- assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
- assert!(!" _ ".chars().all(|c| c.is_whitespace()));
-}
-
-#[test]
-fn test_is_utf8() {
- // deny overlong encodings
- assert!(from_utf8(&[0xc0, 0x80]).is_err());
- assert!(from_utf8(&[0xc0, 0xae]).is_err());
- assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
- assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
- assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
- assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
- assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
-
- // deny surrogates
- assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
- assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
-
- assert!(from_utf8(&[0xC2, 0x80]).is_ok());
- assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
- assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
- assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
- assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
- assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
- assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
- assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
-}
-
-#[test]
-fn from_utf8_mostly_ascii() {
- // deny invalid bytes embedded in long stretches of ascii
- for i in 32..64 {
- let mut data = [0; 128];
- data[i] = 0xC0;
- assert!(from_utf8(&data).is_err());
- data[i] = 0xC2;
- assert!(from_utf8(&data).is_err());
- }
-}
-
-#[test]
-fn from_utf8_error() {
- macro_rules! test {
- ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
- let error = from_utf8($input).unwrap_err();
- assert_eq!(error.valid_up_to(), $expected_valid_up_to);
- assert_eq!(error.error_len(), $expected_error_len);
- }
- }
- test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
- test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
- test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
- test!(b"A\xC3\xA9 \xC1", 4, Some(1));
- test!(b"A\xC3\xA9 \xC2", 4, None);
- test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
- test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
- test!(b"A\xC3\xA9 \xE0", 4, None);
- test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
- test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
- test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
- test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
- test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
- test!(b"A\xC3\xA9 \xF1", 4, None);
- test!(b"A\xC3\xA9 \xF1\x80", 4, None);
- test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
- test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
- test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
- test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
-}
-
-#[test]
-fn test_as_bytes() {
- // no null
- let v = [
- 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
- 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
- 109
- ];
- let b: &[u8] = &[];
- assert_eq!("".as_bytes(), b);
- assert_eq!("abc".as_bytes(), b"abc");
- assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
-}
-
-#[test]
-#[should_panic]
-fn test_as_bytes_fail() {
- // Don't double free. (I'm not sure if this exercises the
- // original problem code path anymore.)
- let s = String::from("");
- let _bytes = s.as_bytes();
- panic!();
-}
-
-#[test]
-fn test_as_ptr() {
- let buf = "hello".as_ptr();
- unsafe {
- assert_eq!(*buf.offset(0), b'h');
- assert_eq!(*buf.offset(1), b'e');
- assert_eq!(*buf.offset(2), b'l');
- assert_eq!(*buf.offset(3), b'l');
- assert_eq!(*buf.offset(4), b'o');
- }
-}
-
-#[test]
-fn vec_str_conversions() {
- let s1: String = String::from("All mimsy were the borogoves");
-
- let v: Vec<u8> = s1.as_bytes().to_vec();
- let s2: String = String::from(from_utf8(&v).unwrap());
- let mut i = 0;
- let n1 = s1.len();
- let n2 = v.len();
- assert_eq!(n1, n2);
- while i < n1 {
- let a: u8 = s1.as_bytes()[i];
- let b: u8 = s2.as_bytes()[i];
- assert_eq!(a, b);
- i += 1;
- }
-}
-
-#[test]
-fn test_contains() {
- assert!("abcde".contains("bcd"));
- assert!("abcde".contains("abcd"));
- assert!("abcde".contains("bcde"));
- assert!("abcde".contains(""));
- assert!("".contains(""));
- assert!(!"abcde".contains("def"));
- assert!(!"".contains("a"));
-
- let data = "ประเทศไทย中华Việt Nam";
- assert!(data.contains("ประเ"));
- assert!(data.contains("ะเ"));
- assert!(data.contains("中华"));
- assert!(!data.contains("ไท华"));
-}
-
-#[test]
-fn test_contains_char() {
- assert!("abc".contains('b'));
- assert!("a".contains('a'));
- assert!(!"abc".contains('d'));
- assert!(!"".contains('a'));
-}
-
-#[test]
-fn test_split_at() {
- let s = "ศไทย中华Việt Nam";
- for (index, _) in s.char_indices() {
- let (a, b) = s.split_at(index);
- assert_eq!(&s[..a.len()], a);
- assert_eq!(&s[a.len()..], b);
- }
- let (a, b) = s.split_at(s.len());
- assert_eq!(a, s);
- assert_eq!(b, "");
-}
-
-#[test]
-fn test_split_at_mut() {
- use std::ascii::AsciiExt;
- let mut s = "Hello World".to_string();
- {
- let (a, b) = s.split_at_mut(5);
- a.make_ascii_uppercase();
- b.make_ascii_lowercase();
- }
- assert_eq!(s, "HELLO world");
-}
-
-#[test]
-#[should_panic]
-fn test_split_at_boundscheck() {
- let s = "ศไทย中华Việt Nam";
- s.split_at(1);
-}
-
-#[test]
-fn test_escape_unicode() {
- assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
- assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
- assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
- assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
- assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
- assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
- assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
- assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
- assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
-}
-
-#[test]
-fn test_escape_debug() {
- assert_eq!("abc".escape_debug(), "abc");
- assert_eq!("a c".escape_debug(), "a c");
- assert_eq!("éèê".escape_debug(), "éèê");
- assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
- assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
- assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
- assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
- assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
- assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
- assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
-}
-
-#[test]
-fn test_escape_default() {
- assert_eq!("abc".escape_default(), "abc");
- assert_eq!("a c".escape_default(), "a c");
- assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
- assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
- assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
- assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
- assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
- assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
- assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
- assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
-}
-
-#[test]
-fn test_total_ord() {
- assert_eq!("1234".cmp("123"), Greater);
- assert_eq!("123".cmp("1234"), Less);
- assert_eq!("1234".cmp("1234"), Equal);
- assert_eq!("12345555".cmp("123456"), Less);
- assert_eq!("22".cmp("1234"), Greater);
-}
-
-#[test]
-fn test_iterator() {
- let s = "ศไทย中华Việt Nam";
- let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
-
- let mut pos = 0;
- let it = s.chars();
-
- for c in it {
- assert_eq!(c, v[pos]);
- pos += 1;
- }
- assert_eq!(pos, v.len());
- assert_eq!(s.chars().count(), v.len());
-}
-
-#[test]
-fn test_rev_iterator() {
- let s = "ศไทย中华Việt Nam";
- let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
-
- let mut pos = 0;
- let it = s.chars().rev();
-
- for c in it {
- assert_eq!(c, v[pos]);
- pos += 1;
- }
- assert_eq!(pos, v.len());
-}
-
-#[test]
-fn test_chars_decoding() {
- let mut bytes = [0; 4];
- for c in (0..0x110000).filter_map(::std::char::from_u32) {
- let s = c.encode_utf8(&mut bytes);
- if Some(c) != s.chars().next() {
- panic!("character {:x}={} does not decode correctly", c as u32, c);
- }
- }
-}
-
-#[test]
-fn test_chars_rev_decoding() {
- let mut bytes = [0; 4];
- for c in (0..0x110000).filter_map(::std::char::from_u32) {
- let s = c.encode_utf8(&mut bytes);
- if Some(c) != s.chars().rev().next() {
- panic!("character {:x}={} does not decode correctly", c as u32, c);
- }
- }
-}
-
-#[test]
-fn test_iterator_clone() {
- let s = "ศไทย中华Việt Nam";
- let mut it = s.chars();
- it.next();
- assert!(it.clone().zip(it).all(|(x,y)| x == y));
-}
-
-#[test]
-fn test_iterator_last() {
- let s = "ศไทย中华Việt Nam";
- let mut it = s.chars();
- it.next();
- assert_eq!(it.last(), Some('m'));
-}
-
-#[test]
-fn test_bytesator() {
- let s = "ศไทย中华Việt Nam";
- let v = [
- 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
- 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
- 109
- ];
- let mut pos = 0;
-
- for b in s.bytes() {
- assert_eq!(b, v[pos]);
- pos += 1;
- }
-}
-
-#[test]
-fn test_bytes_revator() {
- let s = "ศไทย中华Việt Nam";
- let v = [
- 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
- 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
- 109
- ];
- let mut pos = v.len();
-
- for b in s.bytes().rev() {
- pos -= 1;
- assert_eq!(b, v[pos]);
- }
-}
-
-#[test]
-fn test_bytesator_nth() {
- let s = "ศไทย中华Việt Nam";
- let v = [
- 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
- 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
- 109
- ];
-
- let mut b = s.bytes();
- assert_eq!(b.nth(2).unwrap(), v[2]);
- assert_eq!(b.nth(10).unwrap(), v[10]);
- assert_eq!(b.nth(200), None);
-}
-
-#[test]
-fn test_bytesator_count() {
- let s = "ศไทย中华Việt Nam";
-
- let b = s.bytes();
- assert_eq!(b.count(), 28)
-}
-
-#[test]
-fn test_bytesator_last() {
- let s = "ศไทย中华Việt Nam";
-
- let b = s.bytes();
- assert_eq!(b.last().unwrap(), 109)
-}
-
-#[test]
-fn test_char_indicesator() {
- let s = "ศไทย中华Việt Nam";
- let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
- let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
-
- let mut pos = 0;
- let it = s.char_indices();
-
- for c in it {
- assert_eq!(c, (p[pos], v[pos]));
- pos += 1;
- }
- assert_eq!(pos, v.len());
- assert_eq!(pos, p.len());
-}
-
-#[test]
-fn test_char_indices_revator() {
- let s = "ศไทย中华Việt Nam";
- let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
- let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
-
- let mut pos = 0;
- let it = s.char_indices().rev();
-
- for c in it {
- assert_eq!(c, (p[pos], v[pos]));
- pos += 1;
- }
- assert_eq!(pos, v.len());
- assert_eq!(pos, p.len());
-}
-
-#[test]
-fn test_char_indices_last() {
- let s = "ศไทย中华Việt Nam";
- let mut it = s.char_indices();
- it.next();
- assert_eq!(it.last(), Some((27, 'm')));
-}
-
-#[test]
-fn test_splitn_char_iterator() {
- let data = "\nMäry häd ä little lämb\nLittle lämb\n";
-
- let split: Vec<&str> = data.splitn(4, ' ').collect();
- assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
-
- let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
- assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
-
- // Unicode
- let split: Vec<&str> = data.splitn(4, 'ä').collect();
- assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
-
- let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
- assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
-}
-
-#[test]
-fn test_split_char_iterator_no_trailing() {
- let data = "\nMäry häd ä little lämb\nLittle lämb\n";
-
- let split: Vec<&str> = data.split('\n').collect();
- assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
-
- let split: Vec<&str> = data.split_terminator('\n').collect();
- assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
-}
-
-#[test]
-fn test_rsplit() {
- let data = "\nMäry häd ä little lämb\nLittle lämb\n";
-
- let split: Vec<&str> = data.rsplit(' ').collect();
- assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
-
- let split: Vec<&str> = data.rsplit("lämb").collect();
- assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
-
- let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
- assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
-}
-
-#[test]
-fn test_rsplitn() {
- let data = "\nMäry häd ä little lämb\nLittle lämb\n";
-
- let split: Vec<&str> = data.rsplitn(2, ' ').collect();
- assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
-
- let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
- assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
-
- let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
- assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
-}
-
-#[test]
-fn test_split_whitespace() {
- let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
- let words: Vec<&str> = data.split_whitespace().collect();
- assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
-}
-
-#[test]
-fn test_lines() {
- let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
- let lines: Vec<&str> = data.lines().collect();
- assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
-
- let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
- let lines: Vec<&str> = data.lines().collect();
- assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
-}
-
-#[test]
-fn test_splitator() {
- fn t(s: &str, sep: &str, u: &[&str]) {
- let v: Vec<&str> = s.split(sep).collect();
- assert_eq!(v, u);
- }
- t("--1233345--", "12345", &["--1233345--"]);
- t("abc::hello::there", "::", &["abc", "hello", "there"]);
- t("::hello::there", "::", &["", "hello", "there"]);
- t("hello::there::", "::", &["hello", "there", ""]);
- t("::hello::there::", "::", &["", "hello", "there", ""]);
- t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
- t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
- t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
- t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
- t("", ".", &[""]);
- t("zz", "zz", &["",""]);
- t("ok", "z", &["ok"]);
- t("zzz", "zz", &["","z"]);
- t("zzzzz", "zz", &["","","z"]);
-}
-
-#[test]
-fn test_str_default() {
- use std::default::Default;
-
- fn t<S: Default + AsRef<str>>() {
- let s: S = Default::default();
- assert_eq!(s.as_ref(), "");
- }
-
- t::<&str>();
- t::<String>();
-}
-
-#[test]
-fn test_str_container() {
- fn sum_len(v: &[&str]) -> usize {
- v.iter().map(|x| x.len()).sum()
- }
-
- let s = "01234";
- assert_eq!(5, sum_len(&["012", "", "34"]));
- assert_eq!(5, sum_len(&["01", "2", "34", ""]));
- assert_eq!(5, sum_len(&[s]));
-}
-
-#[test]
-fn test_str_from_utf8() {
- let xs = b"hello";
- assert_eq!(from_utf8(xs), Ok("hello"));
-
- let xs = "ศไทย中华Việt Nam".as_bytes();
- assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
-
- let xs = b"hello\xFF";
- assert!(from_utf8(xs).is_err());
-}
-
-#[test]
-fn test_pattern_deref_forward() {
- let data = "aabcdaa";
- assert!(data.contains("bcd"));
- assert!(data.contains(&"bcd"));
- assert!(data.contains(&"bcd".to_string()));
-}
-
-#[test]
-fn test_empty_match_indices() {
- let data = "aä中!";
- let vec: Vec<_> = data.match_indices("").collect();
- assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
-}
-
-#[test]
-fn test_bool_from_str() {
- assert_eq!("true".parse().ok(), Some(true));
- assert_eq!("false".parse().ok(), Some(false));
- assert_eq!("not even a boolean".parse::<bool>().ok(), None);
-}
-
-fn check_contains_all_substrings(s: &str) {
- assert!(s.contains(""));
- for i in 0..s.len() {
- for j in i+1..s.len() + 1 {
- assert!(s.contains(&s[i..j]));
- }
- }
-}
-
-#[test]
-fn strslice_issue_16589() {
- assert!("bananas".contains("nana"));
-
- // prior to the fix for #16589, x.contains("abcdabcd") returned false
- // test all substrings for good measure
- check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
-}
-
-#[test]
-fn strslice_issue_16878() {
- assert!(!"1234567ah012345678901ah".contains("hah"));
- assert!(!"00abc01234567890123456789abc".contains("bcabc"));
-}
-
-
-#[test]
-fn test_strslice_contains() {
- let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
- check_contains_all_substrings(x);
-}
-
-#[test]
-fn test_rsplitn_char_iterator() {
- let data = "\nMäry häd ä little lämb\nLittle lämb\n";
-
- let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
- split.reverse();
- assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
-
- let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
- split.reverse();
- assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
-
- // Unicode
- let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
- split.reverse();
- assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
-
- let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
- split.reverse();
- assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
-}
-
-#[test]
-fn test_split_char_iterator() {
- let data = "\nMäry häd ä little lämb\nLittle lämb\n";
-
- let split: Vec<&str> = data.split(' ').collect();
- assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
-
- let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
- rsplit.reverse();
- assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
-
- let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
- assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
-
- let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
- rsplit.reverse();
- assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
-
- // Unicode
- let split: Vec<&str> = data.split('ä').collect();
- assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
-
- let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
- rsplit.reverse();
- assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
-
- let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
- assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
-
- let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
- rsplit.reverse();
- assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
-}
-
-#[test]
-fn test_rev_split_char_iterator_no_trailing() {
- let data = "\nMäry häd ä little lämb\nLittle lämb\n";
-
- let mut split: Vec<&str> = data.split('\n').rev().collect();
- split.reverse();
- assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
-
- let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
- split.reverse();
- assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
-}
-
-#[test]
-fn test_utf16_code_units() {
- use std_unicode::str::Utf16Encoder;
- assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
- [0xE9, 0xD83D, 0xDCA9])
-}
-
-#[test]
-fn starts_with_in_unicode() {
- assert!(!"├── Cargo.toml".starts_with("# "));
-}
-
-#[test]
-fn starts_short_long() {
- assert!(!"".starts_with("##"));
- assert!(!"##".starts_with("####"));
- assert!("####".starts_with("##"));
- assert!(!"##ä".starts_with("####"));
- assert!("####ä".starts_with("##"));
- assert!(!"##".starts_with("####ä"));
- assert!("##ä##".starts_with("##ä"));
-
- assert!("".starts_with(""));
- assert!("ä".starts_with(""));
- assert!("#ä".starts_with(""));
- assert!("##ä".starts_with(""));
- assert!("ä###".starts_with(""));
- assert!("#ä##".starts_with(""));
- assert!("##ä#".starts_with(""));
-}
-
-#[test]
-fn contains_weird_cases() {
- assert!("* \t".contains(' '));
- assert!(!"* \t".contains('?'));
- assert!(!"* \t".contains('\u{1F4A9}'));
-}
-
-#[test]
-fn trim_ws() {
- assert_eq!(" \t a \t ".trim_left_matches(|c: char| c.is_whitespace()),
- "a \t ");
- assert_eq!(" \t a \t ".trim_right_matches(|c: char| c.is_whitespace()),
- " \t a");
- assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
- "a");
- assert_eq!(" \t \t ".trim_left_matches(|c: char| c.is_whitespace()),
- "");
- assert_eq!(" \t \t ".trim_right_matches(|c: char| c.is_whitespace()),
- "");
- assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
- "");
-}
-
-#[test]
-fn to_lowercase() {
- assert_eq!("".to_lowercase(), "");
- assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
-
- // https://github.com/rust-lang/rust/issues/26035
- assert_eq!("ΑΣ".to_lowercase(), "ας");
- assert_eq!("Α'Σ".to_lowercase(), "α'ς");
- assert_eq!("Α''Σ".to_lowercase(), "α''ς");
-
- assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
- assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
- assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
-
- assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
- assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
-
- assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
- assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
-
- assert_eq!("Α Σ".to_lowercase(), "α σ");
- assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
- assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
-
- assert_eq!("Σ".to_lowercase(), "σ");
- assert_eq!("'Σ".to_lowercase(), "'σ");
- assert_eq!("''Σ".to_lowercase(), "''σ");
-
- assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
- assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
- assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
-}
-
-#[test]
-fn to_uppercase() {
- assert_eq!("".to_uppercase(), "");
- assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
-}
-
-#[test]
-fn test_into_string() {
- // The only way to acquire a Box<str> in the first place is through a String, so just
- // test that we can round-trip between Box<str> and String.
- let string = String::from("Some text goes here");
- assert_eq!(string.clone().into_boxed_str().into_string(), string);
-}
-
-#[test]
-fn test_box_slice_clone() {
- let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
- let data2 = data.clone().into_boxed_str().clone().into_string();
-
- assert_eq!(data, data2);
-}
-
-#[test]
-fn test_cow_from() {
- let borrowed = "borrowed";
- let owned = String::from("owned");
- match (Cow::from(owned.clone()), Cow::from(borrowed)) {
- (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
- _ => panic!("invalid `Cow::from`"),
- }
-}
-
-#[test]
-fn test_repeat() {
- assert_eq!("".repeat(3), "");
- assert_eq!("abc".repeat(0), "");
- assert_eq!("α".repeat(3), "ααα");
-}
-
-mod pattern {
- use std::str::pattern::Pattern;
- use std::str::pattern::{Searcher, ReverseSearcher};
- use std::str::pattern::SearchStep::{self, Match, Reject, Done};
-
- macro_rules! make_test {
- ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
- #[allow(unused_imports)]
- mod $name {
- use std::str::pattern::SearchStep::{Match, Reject};
- use super::{cmp_search_to_vec};
- #[test]
- fn fwd() {
- cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
- }
- #[test]
- fn bwd() {
- cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
- }
- }
- }
- }
-
- fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
- right: Vec<SearchStep>)
- where P::Searcher: ReverseSearcher<'a>
- {
- let mut searcher = pat.into_searcher(haystack);
- let mut v = vec![];
- loop {
- match if !rev {searcher.next()} else {searcher.next_back()} {
- Match(a, b) => v.push(Match(a, b)),
- Reject(a, b) => v.push(Reject(a, b)),
- Done => break,
- }
- }
- if rev {
- v.reverse();
- }
-
- let mut first_index = 0;
- let mut err = None;
-
- for (i, e) in right.iter().enumerate() {
- match *e {
- Match(a, b) | Reject(a, b)
- if a <= b && a == first_index => {
- first_index = b;
- }
- _ => {
- err = Some(i);
- break;
- }
- }
- }
-
- if let Some(err) = err {
- panic!("Input skipped range at {}", err);
- }
-
- if first_index != haystack.len() {
- panic!("Did not cover whole input");
- }
-
- assert_eq!(v, right);
- }
-
- make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
- Reject(0, 1),
- Match (1, 3),
- Reject(3, 4),
- Match (4, 6),
- Reject(6, 7),
- ]);
- make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
- Reject(0, 1),
- Match (1, 3),
- Reject(3, 4),
- Match (4, 6),
- Match (6, 8),
- Reject(8, 9),
- ]);
- make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
- Match (0, 0),
- Reject(0, 1),
- Match (1, 1),
- Reject(1, 2),
- Match (2, 2),
- Reject(2, 3),
- Match (3, 3),
- Reject(3, 4),
- Match (4, 4),
- Reject(4, 5),
- Match (5, 5),
- Reject(5, 6),
- Match (6, 6),
- Reject(6, 7),
- Match (7, 7),
- ]);
- make_test!(str_searcher_mulibyte_haystack, " ", "├──", [
- Reject(0, 3),
- Reject(3, 6),
- Reject(6, 9),
- ]);
- make_test!(str_searcher_empty_needle_mulibyte_haystack, "", "├──", [
- Match (0, 0),
- Reject(0, 3),
- Match (3, 3),
- Reject(3, 6),
- Match (6, 6),
- Reject(6, 9),
- Match (9, 9),
- ]);
- make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
- Match(0, 0),
- ]);
- make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
- ]);
- make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
- Reject(0, 1),
- Match (1, 2),
- Match (2, 3),
- Reject(3, 4),
- Match (4, 5),
- Match (5, 6),
- Reject(6, 7),
- ]);
- make_test!(char_searcher_mulibyte_haystack, ' ', "├──", [
- Reject(0, 3),
- Reject(3, 6),
- Reject(6, 9),
- ]);
- make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
- Reject(0, 1),
- Reject(1, 2),
- Reject(2, 3),
- ]);
-
-}
-
-macro_rules! generate_iterator_test {
- {
- $name:ident {
- $(
- ($($arg:expr),*) -> [$($t:tt)*];
- )*
- }
- with $fwd:expr, $bwd:expr;
- } => {
- #[test]
- fn $name() {
- $(
- {
- let res = vec![$($t)*];
-
- let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
- assert_eq!(fwd_vec, res);
-
- let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
- bwd_vec.reverse();
- assert_eq!(bwd_vec, res);
- }
- )*
- }
- };
- {
- $name:ident {
- $(
- ($($arg:expr),*) -> [$($t:tt)*];
- )*
- }
- with $fwd:expr;
- } => {
- #[test]
- fn $name() {
- $(
- {
- let res = vec![$($t)*];
-
- let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
- assert_eq!(fwd_vec, res);
- }
- )*
- }
- }
-}
-
-generate_iterator_test! {
- double_ended_split {
- ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
- ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
- }
- with str::split, str::rsplit;
-}
-
-generate_iterator_test! {
- double_ended_split_terminator {
- ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
- }
- with str::split_terminator, str::rsplit_terminator;
-}
-
-generate_iterator_test! {
- double_ended_matches {
- ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
- }
- with str::matches, str::rmatches;
-}
-
-generate_iterator_test! {
- double_ended_match_indices {
- ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
- }
- with str::match_indices, str::rmatch_indices;
-}
-
-generate_iterator_test! {
- not_double_ended_splitn {
- ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
- }
- with str::splitn;
-}
-
-generate_iterator_test! {
- not_double_ended_rsplitn {
- ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
- }
- with str::rsplitn;
-}
-
-#[test]
-fn different_str_pattern_forwarding_lifetimes() {
- use std::str::pattern::Pattern;
-
- fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
- for _ in 0..3 {
- "asdf".find(&p);
- }
- }
-
- foo::<&str>("x");
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use std::borrow::Cow;
-
-pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
- fn into_cow(self) -> Cow<'a, B>;
-}
-
-impl<'a> IntoCow<'a, str> for String {
- fn into_cow(self) -> Cow<'a, str> {
- Cow::Owned(self)
- }
-}
-
-impl<'a> IntoCow<'a, str> for &'a str {
- fn into_cow(self) -> Cow<'a, str> {
- Cow::Borrowed(self)
- }
-}
-
-#[test]
-fn test_from_str() {
- let owned: Option<::std::string::String> = "string".parse().ok();
- assert_eq!(owned.as_ref().map(|s| &**s), Some("string"));
-}
-
-#[test]
-fn test_from_cow_str() {
- assert_eq!(String::from(Cow::Borrowed("string")), "string");
- assert_eq!(String::from(Cow::Owned(String::from("string"))), "string");
-}
-
-#[test]
-fn test_unsized_to_string() {
- let s: &str = "abc";
- let _: String = (*s).to_string();
-}
-
-#[test]
-fn test_from_utf8() {
- let xs = b"hello".to_vec();
- assert_eq!(String::from_utf8(xs).unwrap(), String::from("hello"));
-
- let xs = "ศไทย中华Việt Nam".as_bytes().to_vec();
- assert_eq!(String::from_utf8(xs).unwrap(),
- String::from("ศไทย中华Việt Nam"));
-
- let xs = b"hello\xFF".to_vec();
- let err = String::from_utf8(xs).unwrap_err();
- assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
-}
-
-#[test]
-fn test_from_utf8_lossy() {
- let xs = b"hello";
- let ys: Cow<str> = "hello".into_cow();
- assert_eq!(String::from_utf8_lossy(xs), ys);
-
- let xs = "ศไทย中华Việt Nam".as_bytes();
- let ys: Cow<str> = "ศไทย中华Việt Nam".into_cow();
- assert_eq!(String::from_utf8_lossy(xs), ys);
-
- let xs = b"Hello\xC2 There\xFF Goodbye";
- assert_eq!(String::from_utf8_lossy(xs),
- String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow());
-
- let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
- assert_eq!(String::from_utf8_lossy(xs),
- String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow());
-
- let xs = b"\xF5foo\xF5\x80bar";
- assert_eq!(String::from_utf8_lossy(xs),
- String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow());
-
- let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
- assert_eq!(String::from_utf8_lossy(xs),
- String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow());
-
- let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
- assert_eq!(String::from_utf8_lossy(xs),
- String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow());
-
- let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
- assert_eq!(String::from_utf8_lossy(xs),
- String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar").into_cow());
-
- // surrogates
- let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
- assert_eq!(String::from_utf8_lossy(xs),
- String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow());
-}
-
-#[test]
-fn test_from_utf16() {
- let pairs = [(String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
- vec![0xd800, 0xdf45, 0xd800, 0xdf3f, 0xd800, 0xdf3b, 0xd800, 0xdf46, 0xd800,
- 0xdf39, 0xd800, 0xdf3b, 0xd800, 0xdf30, 0x000a]),
-
- (String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
- vec![0xd801, 0xdc12, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc40, 0xd801,
- 0xdc32, 0xd801, 0xdc4b, 0x0020, 0xd801, 0xdc0f, 0xd801, 0xdc32, 0xd801,
- 0xdc4d, 0x000a]),
-
- (String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
- vec![0xd800, 0xdf00, 0xd800, 0xdf16, 0xd800, 0xdf0b, 0xd800, 0xdf04, 0xd800,
- 0xdf11, 0xd800, 0xdf09, 0x00b7, 0xd800, 0xdf0c, 0xd800, 0xdf04, 0xd800,
- 0xdf15, 0xd800, 0xdf04, 0xd800, 0xdf0b, 0xd800, 0xdf09, 0xd800, 0xdf11,
- 0x000a]),
-
- (String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
- vec![0xd801, 0xdc8b, 0xd801, 0xdc98, 0xd801, 0xdc88, 0xd801, 0xdc91, 0xd801,
- 0xdc9b, 0xd801, 0xdc92, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc93, 0x0020,
- 0xd801, 0xdc88, 0xd801, 0xdc9a, 0xd801, 0xdc8d, 0x0020, 0xd801, 0xdc8f,
- 0xd801, 0xdc9c, 0xd801, 0xdc92, 0xd801, 0xdc96, 0xd801, 0xdc86, 0x0020,
- 0xd801, 0xdc95, 0xd801, 0xdc86, 0x000a]),
- // Issue #12318, even-numbered non-BMP planes
- (String::from("\u{20000}"), vec![0xD840, 0xDC00])];
-
- for p in &pairs {
- let (s, u) = (*p).clone();
- let s_as_utf16 = s.encode_utf16().collect::<Vec<u16>>();
- let u_as_string = String::from_utf16(&u).unwrap();
-
- assert!(::std_unicode::char::decode_utf16(u.iter().cloned()).all(|r| r.is_ok()));
- assert_eq!(s_as_utf16, u);
-
- assert_eq!(u_as_string, s);
- assert_eq!(String::from_utf16_lossy(&u), s);
-
- assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s);
- assert_eq!(u_as_string.encode_utf16().collect::<Vec<u16>>(), u);
- }
-}
-
-#[test]
-fn test_utf16_invalid() {
- // completely positive cases tested above.
- // lead + eof
- assert!(String::from_utf16(&[0xD800]).is_err());
- // lead + lead
- assert!(String::from_utf16(&[0xD800, 0xD800]).is_err());
-
- // isolated trail
- assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err());
-
- // general
- assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err());
-}
-
-#[test]
-fn test_from_utf16_lossy() {
- // completely positive cases tested above.
- // lead + eof
- assert_eq!(String::from_utf16_lossy(&[0xD800]),
- String::from("\u{FFFD}"));
- // lead + lead
- assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]),
- String::from("\u{FFFD}\u{FFFD}"));
-
- // isolated trail
- assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]),
- String::from("a\u{FFFD}"));
-
- // general
- assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]),
- String::from("\u{FFFD}𐒋\u{FFFD}"));
-}
-
-#[test]
-fn test_push_bytes() {
- let mut s = String::from("ABC");
- unsafe {
- let mv = s.as_mut_vec();
- mv.extend_from_slice(&[b'D']);
- }
- assert_eq!(s, "ABCD");
-}
-
-#[test]
-fn test_push_str() {
- let mut s = String::new();
- s.push_str("");
- assert_eq!(&s[0..], "");
- s.push_str("abc");
- assert_eq!(&s[0..], "abc");
- s.push_str("ประเทศไทย中华Việt Nam");
- assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam");
-}
-
-#[test]
-fn test_add_assign() {
- let mut s = String::new();
- s += "";
- assert_eq!(s.as_str(), "");
- s += "abc";
- assert_eq!(s.as_str(), "abc");
- s += "ประเทศไทย中华Việt Nam";
- assert_eq!(s.as_str(), "abcประเทศไทย中华Việt Nam");
-}
-
-#[test]
-fn test_push() {
- let mut data = String::from("ประเทศไทย中");
- data.push('华');
- data.push('b'); // 1 byte
- data.push('¢'); // 2 byte
- data.push('€'); // 3 byte
- data.push('𤭢'); // 4 byte
- assert_eq!(data, "ประเทศไทย中华b¢€𤭢");
-}
-
-#[test]
-fn test_pop() {
- let mut data = String::from("ประเทศไทย中华b¢€𤭢");
- assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes
- assert_eq!(data.pop().unwrap(), '€'); // 3 bytes
- assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes
- assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes
- assert_eq!(data.pop().unwrap(), '华');
- assert_eq!(data, "ประเทศไทย中");
-}
-
-#[test]
-fn test_split_off_empty() {
- let orig = "Hello, world!";
- let mut split = String::from(orig);
- let empty: String = split.split_off(orig.len());
- assert!(empty.is_empty());
-}
-
-#[test]
-#[should_panic]
-fn test_split_off_past_end() {
- let orig = "Hello, world!";
- let mut split = String::from(orig);
- split.split_off(orig.len() + 1);
-}
-
-#[test]
-#[should_panic]
-fn test_split_off_mid_char() {
- let mut orig = String::from("山");
- orig.split_off(1);
-}
-
-#[test]
-fn test_split_off_ascii() {
- let mut ab = String::from("ABCD");
- let cd = ab.split_off(2);
- assert_eq!(ab, "AB");
- assert_eq!(cd, "CD");
-}
-
-#[test]
-fn test_split_off_unicode() {
- let mut nihon = String::from("日本語");
- let go = nihon.split_off("日本".len());
- assert_eq!(nihon, "日本");
- assert_eq!(go, "語");
-}
-
-#[test]
-fn test_str_truncate() {
- let mut s = String::from("12345");
- s.truncate(5);
- assert_eq!(s, "12345");
- s.truncate(3);
- assert_eq!(s, "123");
- s.truncate(0);
- assert_eq!(s, "");
-
- let mut s = String::from("12345");
- let p = s.as_ptr();
- s.truncate(3);
- s.push_str("6");
- let p_ = s.as_ptr();
- assert_eq!(p_, p);
-}
-
-#[test]
-fn test_str_truncate_invalid_len() {
- let mut s = String::from("12345");
- s.truncate(6);
- assert_eq!(s, "12345");
-}
-
-#[test]
-#[should_panic]
-fn test_str_truncate_split_codepoint() {
- let mut s = String::from("\u{FC}"); // ü
- s.truncate(1);
-}
-
-#[test]
-fn test_str_clear() {
- let mut s = String::from("12345");
- s.clear();
- assert_eq!(s.len(), 0);
- assert_eq!(s, "");
-}
-
-#[test]
-fn test_str_add() {
- let a = String::from("12345");
- let b = a + "2";
- let b = b + "2";
- assert_eq!(b.len(), 7);
- assert_eq!(b, "1234522");
-}
-
-#[test]
-fn remove() {
- let mut s = "ศไทย中华Việt Nam; foobar".to_string();
- assert_eq!(s.remove(0), 'ศ');
- assert_eq!(s.len(), 33);
- assert_eq!(s, "ไทย中华Việt Nam; foobar");
- assert_eq!(s.remove(17), 'ệ');
- assert_eq!(s, "ไทย中华Vit Nam; foobar");
-}
-
-#[test]
-#[should_panic]
-fn remove_bad() {
- "ศ".to_string().remove(1);
-}
-
-#[test]
-fn insert() {
- let mut s = "foobar".to_string();
- s.insert(0, 'ệ');
- assert_eq!(s, "ệfoobar");
- s.insert(6, 'ย');
- assert_eq!(s, "ệfooยbar");
-}
-
-#[test]
-#[should_panic]
-fn insert_bad1() {
- "".to_string().insert(1, 't');
-}
-#[test]
-#[should_panic]
-fn insert_bad2() {
- "ệ".to_string().insert(1, 't');
-}
-
-#[test]
-fn test_slicing() {
- let s = "foobar".to_string();
- assert_eq!("foobar", &s[..]);
- assert_eq!("foo", &s[..3]);
- assert_eq!("bar", &s[3..]);
- assert_eq!("oob", &s[1..4]);
-}
-
-#[test]
-fn test_simple_types() {
- assert_eq!(1.to_string(), "1");
- assert_eq!((-1).to_string(), "-1");
- assert_eq!(200.to_string(), "200");
- assert_eq!(2.to_string(), "2");
- assert_eq!(true.to_string(), "true");
- assert_eq!(false.to_string(), "false");
- assert_eq!(("hi".to_string()).to_string(), "hi");
-}
-
-#[test]
-fn test_vectors() {
- let x: Vec<i32> = vec![];
- assert_eq!(format!("{:?}", x), "[]");
- assert_eq!(format!("{:?}", vec![1]), "[1]");
- assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]");
- assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == "[[], [1], [1, 1]]");
-}
-
-#[test]
-fn test_from_iterator() {
- let s = "ศไทย中华Việt Nam".to_string();
- let t = "ศไทย中华";
- let u = "Việt Nam";
-
- let a: String = s.chars().collect();
- assert_eq!(s, a);
-
- let mut b = t.to_string();
- b.extend(u.chars());
- assert_eq!(s, b);
-
- let c: String = vec![t, u].into_iter().collect();
- assert_eq!(s, c);
-
- let mut d = t.to_string();
- d.extend(vec![u]);
- assert_eq!(s, d);
-}
-
-#[test]
-fn test_drain() {
- let mut s = String::from("αβγ");
- assert_eq!(s.drain(2..4).collect::<String>(), "β");
- assert_eq!(s, "αγ");
-
- let mut t = String::from("abcd");
- t.drain(..0);
- assert_eq!(t, "abcd");
- t.drain(..1);
- assert_eq!(t, "bcd");
- t.drain(3..);
- assert_eq!(t, "bcd");
- t.drain(..);
- assert_eq!(t, "");
-}
-
-#[test]
-fn test_extend_ref() {
- let mut a = "foo".to_string();
- a.extend(&['b', 'a', 'r']);
-
- assert_eq!(&a, "foobar");
-}
-
-#[test]
-fn test_into_boxed_str() {
- let xs = String::from("hello my name is bob");
- let ys = xs.into_boxed_str();
- assert_eq!(&*ys, "hello my name is bob");
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use std::ascii::AsciiExt;
-use std::borrow::Cow;
-use std::mem::size_of;
-use std::panic;
-use std::vec::{Drain, IntoIter};
-
-struct DropCounter<'a> {
- count: &'a mut u32,
-}
-
-impl<'a> Drop for DropCounter<'a> {
- fn drop(&mut self) {
- *self.count += 1;
- }
-}
-
-#[test]
-fn test_small_vec_struct() {
- assert!(size_of::<Vec<u8>>() == size_of::<usize>() * 3);
-}
-
-#[test]
-fn test_double_drop() {
- struct TwoVec<T> {
- x: Vec<T>,
- y: Vec<T>,
- }
-
- let (mut count_x, mut count_y) = (0, 0);
- {
- let mut tv = TwoVec {
- x: Vec::new(),
- y: Vec::new(),
- };
- tv.x.push(DropCounter { count: &mut count_x });
- tv.y.push(DropCounter { count: &mut count_y });
-
- // If Vec had a drop flag, here is where it would be zeroed.
- // Instead, it should rely on its internal state to prevent
- // doing anything significant when dropped multiple times.
- drop(tv.x);
-
- // Here tv goes out of scope, tv.y should be dropped, but not tv.x.
- }
-
- assert_eq!(count_x, 1);
- assert_eq!(count_y, 1);
-}
-
-#[test]
-fn test_reserve() {
- let mut v = Vec::new();
- assert_eq!(v.capacity(), 0);
-
- v.reserve(2);
- assert!(v.capacity() >= 2);
-
- for i in 0..16 {
- v.push(i);
- }
-
- assert!(v.capacity() >= 16);
- v.reserve(16);
- assert!(v.capacity() >= 32);
-
- v.push(16);
-
- v.reserve(16);
- assert!(v.capacity() >= 33)
-}
-
-#[test]
-fn test_extend() {
- let mut v = Vec::new();
- let mut w = Vec::new();
-
- v.extend(0..3);
- for i in 0..3 {
- w.push(i)
- }
-
- assert_eq!(v, w);
-
- v.extend(3..10);
- for i in 3..10 {
- w.push(i)
- }
-
- assert_eq!(v, w);
-
- v.extend(w.clone()); // specializes to `append`
- assert!(v.iter().eq(w.iter().chain(w.iter())));
-}
-
-#[test]
-fn test_extend_ref() {
- let mut v = vec![1, 2];
- v.extend(&[3, 4, 5]);
-
- assert_eq!(v.len(), 5);
- assert_eq!(v, [1, 2, 3, 4, 5]);
-
- let w = vec![6, 7];
- v.extend(&w);
-
- assert_eq!(v.len(), 7);
- assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);
-}
-
-#[test]
-fn test_slice_from_mut() {
- let mut values = vec![1, 2, 3, 4, 5];
- {
- let slice = &mut values[2..];
- assert!(slice == [3, 4, 5]);
- for p in slice {
- *p += 2;
- }
- }
-
- assert!(values == [1, 2, 5, 6, 7]);
-}
-
-#[test]
-fn test_slice_to_mut() {
- let mut values = vec![1, 2, 3, 4, 5];
- {
- let slice = &mut values[..2];
- assert!(slice == [1, 2]);
- for p in slice {
- *p += 1;
- }
- }
-
- assert!(values == [2, 3, 3, 4, 5]);
-}
-
-#[test]
-fn test_split_at_mut() {
- let mut values = vec![1, 2, 3, 4, 5];
- {
- let (left, right) = values.split_at_mut(2);
- {
- let left: &[_] = left;
- assert!(&left[..left.len()] == &[1, 2]);
- }
- for p in left {
- *p += 1;
- }
-
- {
- let right: &[_] = right;
- assert!(&right[..right.len()] == &[3, 4, 5]);
- }
- for p in right {
- *p += 2;
- }
- }
-
- assert_eq!(values, [2, 3, 5, 6, 7]);
-}
-
-#[test]
-fn test_clone() {
- let v: Vec<i32> = vec![];
- let w = vec![1, 2, 3];
-
- assert_eq!(v, v.clone());
-
- let z = w.clone();
- assert_eq!(w, z);
- // they should be disjoint in memory.
- assert!(w.as_ptr() != z.as_ptr())
-}
-
-#[test]
-fn test_clone_from() {
- let mut v = vec![];
- let three: Vec<Box<_>> = vec![box 1, box 2, box 3];
- let two: Vec<Box<_>> = vec![box 4, box 5];
- // zero, long
- v.clone_from(&three);
- assert_eq!(v, three);
-
- // equal
- v.clone_from(&three);
- assert_eq!(v, three);
-
- // long, short
- v.clone_from(&two);
- assert_eq!(v, two);
-
- // short, long
- v.clone_from(&three);
- assert_eq!(v, three)
-}
-
-#[test]
-fn test_retain() {
- let mut vec = vec![1, 2, 3, 4];
- vec.retain(|&x| x % 2 == 0);
- assert_eq!(vec, [2, 4]);
-}
-
-#[test]
-fn test_dedup() {
- fn case(a: Vec<i32>, b: Vec<i32>) {
- let mut v = a;
- v.dedup();
- assert_eq!(v, b);
- }
- case(vec![], vec![]);
- case(vec![1], vec![1]);
- case(vec![1, 1], vec![1]);
- case(vec![1, 2, 3], vec![1, 2, 3]);
- case(vec![1, 1, 2, 3], vec![1, 2, 3]);
- case(vec![1, 2, 2, 3], vec![1, 2, 3]);
- case(vec![1, 2, 3, 3], vec![1, 2, 3]);
- case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
-}
-
-#[test]
-fn test_dedup_by_key() {
- fn case(a: Vec<i32>, b: Vec<i32>) {
- let mut v = a;
- v.dedup_by_key(|i| *i / 10);
- assert_eq!(v, b);
- }
- case(vec![], vec![]);
- case(vec![10], vec![10]);
- case(vec![10, 11], vec![10]);
- case(vec![10, 20, 30], vec![10, 20, 30]);
- case(vec![10, 11, 20, 30], vec![10, 20, 30]);
- case(vec![10, 20, 21, 30], vec![10, 20, 30]);
- case(vec![10, 20, 30, 31], vec![10, 20, 30]);
- case(vec![10, 11, 20, 21, 22, 30, 31], vec![10, 20, 30]);
-}
-
-#[test]
-fn test_dedup_by() {
- let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
- vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
-
- assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
-}
-
-#[test]
-fn test_dedup_unique() {
- let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
- v0.dedup();
- let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
- v1.dedup();
- let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
- v2.dedup();
- // If the boxed pointers were leaked or otherwise misused, valgrind
- // and/or rt should raise errors.
-}
-
-#[test]
-fn zero_sized_values() {
- let mut v = Vec::new();
- assert_eq!(v.len(), 0);
- v.push(());
- assert_eq!(v.len(), 1);
- v.push(());
- assert_eq!(v.len(), 2);
- assert_eq!(v.pop(), Some(()));
- assert_eq!(v.pop(), Some(()));
- assert_eq!(v.pop(), None);
-
- assert_eq!(v.iter().count(), 0);
- v.push(());
- assert_eq!(v.iter().count(), 1);
- v.push(());
- assert_eq!(v.iter().count(), 2);
-
- for &() in &v {}
-
- assert_eq!(v.iter_mut().count(), 2);
- v.push(());
- assert_eq!(v.iter_mut().count(), 3);
- v.push(());
- assert_eq!(v.iter_mut().count(), 4);
-
- for &mut () in &mut v {}
- unsafe {
- v.set_len(0);
- }
- assert_eq!(v.iter_mut().count(), 0);
-}
-
-#[test]
-fn test_partition() {
- assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3),
- (vec![], vec![]));
- assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4),
- (vec![1, 2, 3], vec![]));
- assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2),
- (vec![1], vec![2, 3]));
- assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0),
- (vec![], vec![1, 2, 3]));
-}
-
-#[test]
-fn test_zip_unzip() {
- let z1 = vec![(1, 4), (2, 5), (3, 6)];
-
- let (left, right): (Vec<_>, Vec<_>) = z1.iter().cloned().unzip();
-
- assert_eq!((1, 4), (left[0], right[0]));
- assert_eq!((2, 5), (left[1], right[1]));
- assert_eq!((3, 6), (left[2], right[2]));
-}
-
-#[test]
-fn test_vec_truncate_drop() {
- static mut DROPS: u32 = 0;
- struct Elem(i32);
- impl Drop for Elem {
- fn drop(&mut self) {
- unsafe {
- DROPS += 1;
- }
- }
- }
-
- let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
- assert_eq!(unsafe { DROPS }, 0);
- v.truncate(3);
- assert_eq!(unsafe { DROPS }, 2);
- v.truncate(0);
- assert_eq!(unsafe { DROPS }, 5);
-}
-
-#[test]
-#[should_panic]
-fn test_vec_truncate_fail() {
- struct BadElem(i32);
- impl Drop for BadElem {
- fn drop(&mut self) {
- let BadElem(ref mut x) = *self;
- if *x == 0xbadbeef {
- panic!("BadElem panic: 0xbadbeef")
- }
- }
- }
-
- let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)];
- v.truncate(0);
-}
-
-#[test]
-fn test_index() {
- let vec = vec![1, 2, 3];
- assert!(vec[1] == 2);
-}
-
-#[test]
-#[should_panic]
-fn test_index_out_of_bounds() {
- let vec = vec![1, 2, 3];
- let _ = vec[3];
-}
-
-#[test]
-#[should_panic]
-fn test_slice_out_of_bounds_1() {
- let x = vec![1, 2, 3, 4, 5];
- &x[!0..];
-}
-
-#[test]
-#[should_panic]
-fn test_slice_out_of_bounds_2() {
- let x = vec![1, 2, 3, 4, 5];
- &x[..6];
-}
-
-#[test]
-#[should_panic]
-fn test_slice_out_of_bounds_3() {
- let x = vec![1, 2, 3, 4, 5];
- &x[!0..4];
-}
-
-#[test]
-#[should_panic]
-fn test_slice_out_of_bounds_4() {
- let x = vec![1, 2, 3, 4, 5];
- &x[1..6];
-}
-
-#[test]
-#[should_panic]
-fn test_slice_out_of_bounds_5() {
- let x = vec![1, 2, 3, 4, 5];
- &x[3..2];
-}
-
-#[test]
-#[should_panic]
-fn test_swap_remove_empty() {
- let mut vec = Vec::<i32>::new();
- vec.swap_remove(0);
-}
-
-#[test]
-fn test_move_items() {
- let vec = vec![1, 2, 3];
- let mut vec2 = vec![];
- for i in vec {
- vec2.push(i);
- }
- assert_eq!(vec2, [1, 2, 3]);
-}
-
-#[test]
-fn test_move_items_reverse() {
- let vec = vec![1, 2, 3];
- let mut vec2 = vec![];
- for i in vec.into_iter().rev() {
- vec2.push(i);
- }
- assert_eq!(vec2, [3, 2, 1]);
-}
-
-#[test]
-fn test_move_items_zero_sized() {
- let vec = vec![(), (), ()];
- let mut vec2 = vec![];
- for i in vec {
- vec2.push(i);
- }
- assert_eq!(vec2, [(), (), ()]);
-}
-
-#[test]
-fn test_drain_items() {
- let mut vec = vec![1, 2, 3];
- let mut vec2 = vec![];
- for i in vec.drain(..) {
- vec2.push(i);
- }
- assert_eq!(vec, []);
- assert_eq!(vec2, [1, 2, 3]);
-}
-
-#[test]
-fn test_drain_items_reverse() {
- let mut vec = vec![1, 2, 3];
- let mut vec2 = vec![];
- for i in vec.drain(..).rev() {
- vec2.push(i);
- }
- assert_eq!(vec, []);
- assert_eq!(vec2, [3, 2, 1]);
-}
-
-#[test]
-fn test_drain_items_zero_sized() {
- let mut vec = vec![(), (), ()];
- let mut vec2 = vec![];
- for i in vec.drain(..) {
- vec2.push(i);
- }
- assert_eq!(vec, []);
- assert_eq!(vec2, [(), (), ()]);
-}
-
-#[test]
-#[should_panic]
-fn test_drain_out_of_bounds() {
- let mut v = vec![1, 2, 3, 4, 5];
- v.drain(5..6);
-}
-
-#[test]
-fn test_drain_range() {
- let mut v = vec![1, 2, 3, 4, 5];
- for _ in v.drain(4..) {
- }
- assert_eq!(v, &[1, 2, 3, 4]);
-
- let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect();
- for _ in v.drain(1..4) {
- }
- assert_eq!(v, &[1.to_string(), 5.to_string()]);
-
- let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect();
- for _ in v.drain(1..4).rev() {
- }
- assert_eq!(v, &[1.to_string(), 5.to_string()]);
-
- let mut v: Vec<_> = vec![(); 5];
- for _ in v.drain(1..4).rev() {
- }
- assert_eq!(v, &[(), ()]);
-}
-
-#[test]
-fn test_drain_inclusive_range() {
- let mut v = vec!['a', 'b', 'c', 'd', 'e'];
- for _ in v.drain(1...3) {
- }
- assert_eq!(v, &['a', 'e']);
-
- let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect();
- for _ in v.drain(1...5) {
- }
- assert_eq!(v, &["0".to_string()]);
-
- let mut v: Vec<String> = (0...5).map(|x| x.to_string()).collect();
- for _ in v.drain(0...5) {
- }
- assert_eq!(v, Vec::<String>::new());
-
- let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect();
- for _ in v.drain(0...3) {
- }
- assert_eq!(v, &["4".to_string(), "5".to_string()]);
-
- let mut v: Vec<_> = (0...1).map(|x| x.to_string()).collect();
- for _ in v.drain(...0) {
- }
- assert_eq!(v, &["1".to_string()]);
-}
-
-#[test]
-fn test_drain_max_vec_size() {
- let mut v = Vec::<()>::with_capacity(usize::max_value());
- unsafe { v.set_len(usize::max_value()); }
- for _ in v.drain(usize::max_value() - 1..) {
- }
- assert_eq!(v.len(), usize::max_value() - 1);
-
- let mut v = Vec::<()>::with_capacity(usize::max_value());
- unsafe { v.set_len(usize::max_value()); }
- for _ in v.drain(usize::max_value() - 1...usize::max_value() - 1) {
- }
- assert_eq!(v.len(), usize::max_value() - 1);
-}
-
-#[test]
-#[should_panic]
-fn test_drain_inclusive_out_of_bounds() {
- let mut v = vec![1, 2, 3, 4, 5];
- v.drain(5...5);
-}
-
-#[test]
-fn test_into_boxed_slice() {
- let xs = vec![1, 2, 3];
- let ys = xs.into_boxed_slice();
- assert_eq!(&*ys, [1, 2, 3]);
-}
-
-#[test]
-fn test_append() {
- let mut vec = vec![1, 2, 3];
- let mut vec2 = vec![4, 5, 6];
- vec.append(&mut vec2);
- assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
- assert_eq!(vec2, []);
-}
-
-#[test]
-fn test_split_off() {
- let mut vec = vec![1, 2, 3, 4, 5, 6];
- let vec2 = vec.split_off(4);
- assert_eq!(vec, [1, 2, 3, 4]);
- assert_eq!(vec2, [5, 6]);
-}
-
-#[test]
-fn test_into_iter_as_slice() {
- let vec = vec!['a', 'b', 'c'];
- let mut into_iter = vec.into_iter();
- assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
- let _ = into_iter.next().unwrap();
- assert_eq!(into_iter.as_slice(), &['b', 'c']);
- let _ = into_iter.next().unwrap();
- let _ = into_iter.next().unwrap();
- assert_eq!(into_iter.as_slice(), &[]);
-}
-
-#[test]
-fn test_into_iter_as_mut_slice() {
- let vec = vec!['a', 'b', 'c'];
- let mut into_iter = vec.into_iter();
- assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
- into_iter.as_mut_slice()[0] = 'x';
- into_iter.as_mut_slice()[1] = 'y';
- assert_eq!(into_iter.next().unwrap(), 'x');
- assert_eq!(into_iter.as_slice(), &['y', 'c']);
-}
-
-#[test]
-fn test_into_iter_debug() {
- let vec = vec!['a', 'b', 'c'];
- let into_iter = vec.into_iter();
- let debug = format!("{:?}", into_iter);
- assert_eq!(debug, "IntoIter(['a', 'b', 'c'])");
-}
-
-#[test]
-fn test_into_iter_count() {
- assert_eq!(vec![1, 2, 3].into_iter().count(), 3);
-}
-
-#[test]
-fn test_into_iter_clone() {
- fn iter_equal<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
- let v: Vec<i32> = it.collect();
- assert_eq!(&v[..], slice);
- }
- let mut it = vec![1, 2, 3].into_iter();
- iter_equal(it.clone(), &[1, 2, 3]);
- assert_eq!(it.next(), Some(1));
- let mut it = it.rev();
- iter_equal(it.clone(), &[3, 2]);
- assert_eq!(it.next(), Some(3));
- iter_equal(it.clone(), &[2]);
- assert_eq!(it.next(), Some(2));
- iter_equal(it.clone(), &[]);
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_cow_from() {
- let borrowed: &[_] = &["borrowed", "(slice)"];
- let owned = vec!["owned", "(vec)"];
- match (Cow::from(owned.clone()), Cow::from(borrowed)) {
- (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
- _ => panic!("invalid `Cow::from`"),
- }
-}
-
-#[test]
-fn test_from_cow() {
- let borrowed: &[_] = &["borrowed", "(slice)"];
- let owned = vec!["owned", "(vec)"];
- assert_eq!(Vec::from(Cow::Borrowed(borrowed)), vec!["borrowed", "(slice)"]);
- assert_eq!(Vec::from(Cow::Owned(owned)), vec!["owned", "(vec)"]);
-}
-
-#[allow(dead_code)]
-fn assert_covariance() {
- fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
- d
- }
- fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> {
- i
- }
-}
-
-#[test]
-fn test_placement() {
- let mut vec = vec![1];
- assert_eq!(vec.place_back() <- 2, &2);
- assert_eq!(vec.len(), 2);
- assert_eq!(vec.place_back() <- 3, &3);
- assert_eq!(vec.len(), 3);
- assert_eq!(&vec, &[1, 2, 3]);
-}
-
-#[test]
-fn test_placement_panic() {
- let mut vec = vec![1, 2, 3];
- fn mkpanic() -> usize { panic!() }
- let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); }));
- assert_eq!(vec.len(), 3);
-}
-
-#[test]
-fn from_into_inner() {
- let vec = vec![1, 2, 3];
- let ptr = vec.as_ptr();
- let vec = vec.into_iter().collect::<Vec<_>>();
- assert_eq!(vec, [1, 2, 3]);
- assert_eq!(vec.as_ptr(), ptr);
-
- let ptr = &vec[1] as *const _;
- let mut it = vec.into_iter();
- it.next().unwrap();
- let vec = it.collect::<Vec<_>>();
- assert_eq!(vec, [2, 3]);
- assert!(ptr != vec.as_ptr());
-}
+++ /dev/null
-// Copyright 2012-2014 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.
-
-use std::collections::VecDeque;
-use std::fmt::Debug;
-use std::collections::vec_deque::{Drain};
-
-use self::Taggy::*;
-use self::Taggypar::*;
-
-#[test]
-fn test_simple() {
- let mut d = VecDeque::new();
- assert_eq!(d.len(), 0);
- d.push_front(17);
- d.push_front(42);
- d.push_back(137);
- assert_eq!(d.len(), 3);
- d.push_back(137);
- assert_eq!(d.len(), 4);
- assert_eq!(*d.front().unwrap(), 42);
- assert_eq!(*d.back().unwrap(), 137);
- let mut i = d.pop_front();
- assert_eq!(i, Some(42));
- i = d.pop_back();
- assert_eq!(i, Some(137));
- i = d.pop_back();
- assert_eq!(i, Some(137));
- i = d.pop_back();
- assert_eq!(i, Some(17));
- assert_eq!(d.len(), 0);
- d.push_back(3);
- assert_eq!(d.len(), 1);
- d.push_front(2);
- assert_eq!(d.len(), 2);
- d.push_back(4);
- assert_eq!(d.len(), 3);
- d.push_front(1);
- assert_eq!(d.len(), 4);
- assert_eq!(d[0], 1);
- assert_eq!(d[1], 2);
- assert_eq!(d[2], 3);
- assert_eq!(d[3], 4);
-}
-
-#[cfg(test)]
-fn test_parameterized<T: Clone + PartialEq + Debug>(a: T, b: T, c: T, d: T) {
- let mut deq = VecDeque::new();
- assert_eq!(deq.len(), 0);
- deq.push_front(a.clone());
- deq.push_front(b.clone());
- deq.push_back(c.clone());
- assert_eq!(deq.len(), 3);
- deq.push_back(d.clone());
- assert_eq!(deq.len(), 4);
- assert_eq!((*deq.front().unwrap()).clone(), b.clone());
- assert_eq!((*deq.back().unwrap()).clone(), d.clone());
- assert_eq!(deq.pop_front().unwrap(), b.clone());
- assert_eq!(deq.pop_back().unwrap(), d.clone());
- assert_eq!(deq.pop_back().unwrap(), c.clone());
- assert_eq!(deq.pop_back().unwrap(), a.clone());
- assert_eq!(deq.len(), 0);
- deq.push_back(c.clone());
- assert_eq!(deq.len(), 1);
- deq.push_front(b.clone());
- assert_eq!(deq.len(), 2);
- deq.push_back(d.clone());
- assert_eq!(deq.len(), 3);
- deq.push_front(a.clone());
- assert_eq!(deq.len(), 4);
- assert_eq!(deq[0].clone(), a.clone());
- assert_eq!(deq[1].clone(), b.clone());
- assert_eq!(deq[2].clone(), c.clone());
- assert_eq!(deq[3].clone(), d.clone());
-}
-
-#[test]
-fn test_push_front_grow() {
- let mut deq = VecDeque::new();
- for i in 0..66 {
- deq.push_front(i);
- }
- assert_eq!(deq.len(), 66);
-
- for i in 0..66 {
- assert_eq!(deq[i], 65 - i);
- }
-
- let mut deq = VecDeque::new();
- for i in 0..66 {
- deq.push_back(i);
- }
-
- for i in 0..66 {
- assert_eq!(deq[i], i);
- }
-}
-
-#[test]
-fn test_index() {
- let mut deq = VecDeque::new();
- for i in 1..4 {
- deq.push_front(i);
- }
- assert_eq!(deq[1], 2);
-}
-
-#[test]
-#[should_panic]
-fn test_index_out_of_bounds() {
- let mut deq = VecDeque::new();
- for i in 1..4 {
- deq.push_front(i);
- }
- deq[3];
-}
-
-#[derive(Clone, PartialEq, Debug)]
-enum Taggy {
- One(i32),
- Two(i32, i32),
- Three(i32, i32, i32),
-}
-
-#[derive(Clone, PartialEq, Debug)]
-enum Taggypar<T> {
- Onepar(T),
- Twopar(T, T),
- Threepar(T, T, T),
-}
-
-#[derive(Clone, PartialEq, Debug)]
-struct RecCy {
- x: i32,
- y: i32,
- t: Taggy,
-}
-
-#[test]
-fn test_param_int() {
- test_parameterized::<i32>(5, 72, 64, 175);
-}
-
-#[test]
-fn test_param_taggy() {
- test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42));
-}
-
-#[test]
-fn test_param_taggypar() {
- test_parameterized::<Taggypar<i32>>(Onepar::<i32>(1),
- Twopar::<i32>(1, 2),
- Threepar::<i32>(1, 2, 3),
- Twopar::<i32>(17, 42));
-}
-
-#[test]
-fn test_param_reccy() {
- let reccy1 = RecCy {
- x: 1,
- y: 2,
- t: One(1),
- };
- let reccy2 = RecCy {
- x: 345,
- y: 2,
- t: Two(1, 2),
- };
- let reccy3 = RecCy {
- x: 1,
- y: 777,
- t: Three(1, 2, 3),
- };
- let reccy4 = RecCy {
- x: 19,
- y: 252,
- t: Two(17, 42),
- };
- test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4);
-}
-
-#[test]
-fn test_with_capacity() {
- let mut d = VecDeque::with_capacity(0);
- d.push_back(1);
- assert_eq!(d.len(), 1);
- let mut d = VecDeque::with_capacity(50);
- d.push_back(1);
- assert_eq!(d.len(), 1);
-}
-
-#[test]
-fn test_with_capacity_non_power_two() {
- let mut d3 = VecDeque::with_capacity(3);
- d3.push_back(1);
-
- // X = None, | = lo
- // [|1, X, X]
- assert_eq!(d3.pop_front(), Some(1));
- // [X, |X, X]
- assert_eq!(d3.front(), None);
-
- // [X, |3, X]
- d3.push_back(3);
- // [X, |3, 6]
- d3.push_back(6);
- // [X, X, |6]
- assert_eq!(d3.pop_front(), Some(3));
-
- // Pushing the lo past half way point to trigger
- // the 'B' scenario for growth
- // [9, X, |6]
- d3.push_back(9);
- // [9, 12, |6]
- d3.push_back(12);
-
- d3.push_back(15);
- // There used to be a bug here about how the
- // VecDeque made growth assumptions about the
- // underlying Vec which didn't hold and lead
- // to corruption.
- // (Vec grows to next power of two)
- // good- [9, 12, 15, X, X, X, X, |6]
- // bug- [15, 12, X, X, X, |6, X, X]
- assert_eq!(d3.pop_front(), Some(6));
-
- // Which leads us to the following state which
- // would be a failure case.
- // bug- [15, 12, X, X, X, X, |X, X]
- assert_eq!(d3.front(), Some(&9));
-}
-
-#[test]
-fn test_reserve_exact() {
- let mut d = VecDeque::new();
- d.push_back(0);
- d.reserve_exact(50);
- assert!(d.capacity() >= 51);
-}
-
-#[test]
-fn test_reserve() {
- let mut d = VecDeque::new();
- d.push_back(0);
- d.reserve(50);
- assert!(d.capacity() >= 51);
-}
-
-#[test]
-fn test_swap() {
- let mut d: VecDeque<_> = (0..5).collect();
- d.pop_front();
- d.swap(0, 3);
- assert_eq!(d.iter().cloned().collect::<Vec<_>>(), [4, 2, 3, 1]);
-}
-
-#[test]
-fn test_iter() {
- let mut d = VecDeque::new();
- assert_eq!(d.iter().next(), None);
- assert_eq!(d.iter().size_hint(), (0, Some(0)));
-
- for i in 0..5 {
- d.push_back(i);
- }
- {
- let b: &[_] = &[&0, &1, &2, &3, &4];
- assert_eq!(d.iter().collect::<Vec<_>>(), b);
- }
-
- for i in 6..9 {
- d.push_front(i);
- }
- {
- let b: &[_] = &[&8, &7, &6, &0, &1, &2, &3, &4];
- assert_eq!(d.iter().collect::<Vec<_>>(), b);
- }
-
- let mut it = d.iter();
- let mut len = d.len();
- loop {
- match it.next() {
- None => break,
- _ => {
- len -= 1;
- assert_eq!(it.size_hint(), (len, Some(len)))
- }
- }
- }
-}
-
-#[test]
-fn test_rev_iter() {
- let mut d = VecDeque::new();
- assert_eq!(d.iter().rev().next(), None);
-
- for i in 0..5 {
- d.push_back(i);
- }
- {
- let b: &[_] = &[&4, &3, &2, &1, &0];
- assert_eq!(d.iter().rev().collect::<Vec<_>>(), b);
- }
-
- for i in 6..9 {
- d.push_front(i);
- }
- let b: &[_] = &[&4, &3, &2, &1, &0, &6, &7, &8];
- assert_eq!(d.iter().rev().collect::<Vec<_>>(), b);
-}
-
-#[test]
-fn test_mut_rev_iter_wrap() {
- let mut d = VecDeque::with_capacity(3);
- assert!(d.iter_mut().rev().next().is_none());
-
- d.push_back(1);
- d.push_back(2);
- d.push_back(3);
- assert_eq!(d.pop_front(), Some(1));
- d.push_back(4);
-
- assert_eq!(d.iter_mut().rev().map(|x| *x).collect::<Vec<_>>(),
- vec![4, 3, 2]);
-}
-
-#[test]
-fn test_mut_iter() {
- let mut d = VecDeque::new();
- assert!(d.iter_mut().next().is_none());
-
- for i in 0..3 {
- d.push_front(i);
- }
-
- for (i, elt) in d.iter_mut().enumerate() {
- assert_eq!(*elt, 2 - i);
- *elt = i;
- }
-
- {
- let mut it = d.iter_mut();
- assert_eq!(*it.next().unwrap(), 0);
- assert_eq!(*it.next().unwrap(), 1);
- assert_eq!(*it.next().unwrap(), 2);
- assert!(it.next().is_none());
- }
-}
-
-#[test]
-fn test_mut_rev_iter() {
- let mut d = VecDeque::new();
- assert!(d.iter_mut().rev().next().is_none());
-
- for i in 0..3 {
- d.push_front(i);
- }
-
- for (i, elt) in d.iter_mut().rev().enumerate() {
- assert_eq!(*elt, i);
- *elt = i;
- }
-
- {
- let mut it = d.iter_mut().rev();
- assert_eq!(*it.next().unwrap(), 0);
- assert_eq!(*it.next().unwrap(), 1);
- assert_eq!(*it.next().unwrap(), 2);
- assert!(it.next().is_none());
- }
-}
-
-#[test]
-fn test_into_iter() {
-
- // Empty iter
- {
- let d: VecDeque<i32> = VecDeque::new();
- let mut iter = d.into_iter();
-
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
- assert_eq!(iter.size_hint(), (0, Some(0)));
- }
-
- // simple iter
- {
- let mut d = VecDeque::new();
- for i in 0..5 {
- d.push_back(i);
- }
-
- let b = vec![0, 1, 2, 3, 4];
- assert_eq!(d.into_iter().collect::<Vec<_>>(), b);
- }
-
- // wrapped iter
- {
- let mut d = VecDeque::new();
- for i in 0..5 {
- d.push_back(i);
- }
- for i in 6..9 {
- d.push_front(i);
- }
-
- let b = vec![8, 7, 6, 0, 1, 2, 3, 4];
- assert_eq!(d.into_iter().collect::<Vec<_>>(), b);
- }
-
- // partially used
- {
- let mut d = VecDeque::new();
- for i in 0..5 {
- d.push_back(i);
- }
- for i in 6..9 {
- d.push_front(i);
- }
-
- let mut it = d.into_iter();
- assert_eq!(it.size_hint(), (8, Some(8)));
- assert_eq!(it.next(), Some(8));
- assert_eq!(it.size_hint(), (7, Some(7)));
- assert_eq!(it.next_back(), Some(4));
- assert_eq!(it.size_hint(), (6, Some(6)));
- assert_eq!(it.next(), Some(7));
- assert_eq!(it.size_hint(), (5, Some(5)));
- }
-}
-
-#[test]
-fn test_drain() {
-
- // Empty iter
- {
- let mut d: VecDeque<i32> = VecDeque::new();
-
- {
- let mut iter = d.drain(..);
-
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
- assert_eq!(iter.size_hint(), (0, Some(0)));
- }
-
- assert!(d.is_empty());
- }
-
- // simple iter
- {
- let mut d = VecDeque::new();
- for i in 0..5 {
- d.push_back(i);
- }
-
- assert_eq!(d.drain(..).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
- assert!(d.is_empty());
- }
-
- // wrapped iter
- {
- let mut d = VecDeque::new();
- for i in 0..5 {
- d.push_back(i);
- }
- for i in 6..9 {
- d.push_front(i);
- }
-
- assert_eq!(d.drain(..).collect::<Vec<_>>(), [8, 7, 6, 0, 1, 2, 3, 4]);
- assert!(d.is_empty());
- }
-
- // partially used
- {
- let mut d: VecDeque<_> = VecDeque::new();
- for i in 0..5 {
- d.push_back(i);
- }
- for i in 6..9 {
- d.push_front(i);
- }
-
- {
- let mut it = d.drain(..);
- assert_eq!(it.size_hint(), (8, Some(8)));
- assert_eq!(it.next(), Some(8));
- assert_eq!(it.size_hint(), (7, Some(7)));
- assert_eq!(it.next_back(), Some(4));
- assert_eq!(it.size_hint(), (6, Some(6)));
- assert_eq!(it.next(), Some(7));
- assert_eq!(it.size_hint(), (5, Some(5)));
- }
- assert!(d.is_empty());
- }
-}
-
-#[test]
-fn test_from_iter() {
- let v = vec![1, 2, 3, 4, 5, 6, 7];
- let deq: VecDeque<_> = v.iter().cloned().collect();
- let u: Vec<_> = deq.iter().cloned().collect();
- assert_eq!(u, v);
-
- let seq = (0..).step_by(2).take(256);
- let deq: VecDeque<_> = seq.collect();
- for (i, &x) in deq.iter().enumerate() {
- assert_eq!(2 * i, x);
- }
- assert_eq!(deq.len(), 256);
-}
-
-#[test]
-fn test_clone() {
- let mut d = VecDeque::new();
- d.push_front(17);
- d.push_front(42);
- d.push_back(137);
- d.push_back(137);
- assert_eq!(d.len(), 4);
- let mut e = d.clone();
- assert_eq!(e.len(), 4);
- while !d.is_empty() {
- assert_eq!(d.pop_back(), e.pop_back());
- }
- assert_eq!(d.len(), 0);
- assert_eq!(e.len(), 0);
-}
-
-#[test]
-fn test_eq() {
- let mut d = VecDeque::new();
- assert!(d == VecDeque::with_capacity(0));
- d.push_front(137);
- d.push_front(17);
- d.push_front(42);
- d.push_back(137);
- let mut e = VecDeque::with_capacity(0);
- e.push_back(42);
- e.push_back(17);
- e.push_back(137);
- e.push_back(137);
- assert!(&e == &d);
- e.pop_back();
- e.push_back(0);
- assert!(e != d);
- e.clear();
- assert!(e == VecDeque::new());
-}
-
-#[test]
-fn test_partial_eq_array() {
- let d = VecDeque::<char>::new();
- assert!(d == []);
-
- let mut d = VecDeque::new();
- d.push_front('a');
- assert!(d == ['a']);
-
- let mut d = VecDeque::new();
- d.push_back('a');
- assert!(d == ['a']);
-
- let mut d = VecDeque::new();
- d.push_back('a');
- d.push_back('b');
- assert!(d == ['a', 'b']);
-}
-
-#[test]
-fn test_hash() {
- let mut x = VecDeque::new();
- let mut y = VecDeque::new();
-
- x.push_back(1);
- x.push_back(2);
- x.push_back(3);
-
- y.push_back(0);
- y.push_back(1);
- y.pop_front();
- y.push_back(2);
- y.push_back(3);
-
- assert!(::hash(&x) == ::hash(&y));
-}
-
-#[test]
-fn test_hash_after_rotation() {
- // test that two deques hash equal even if elements are laid out differently
- let len = 28;
- let mut ring: VecDeque<i32> = (0..len as i32).collect();
- let orig = ring.clone();
- for _ in 0..ring.capacity() {
- // shift values 1 step to the right by pop, sub one, push
- ring.pop_front();
- for elt in &mut ring {
- *elt -= 1;
- }
- ring.push_back(len - 1);
- assert_eq!(::hash(&orig), ::hash(&ring));
- assert_eq!(orig, ring);
- assert_eq!(ring, orig);
- }
-}
-
-#[test]
-fn test_eq_after_rotation() {
- // test that two deques are equal even if elements are laid out differently
- let len = 28;
- let mut ring: VecDeque<i32> = (0..len as i32).collect();
- let mut shifted = ring.clone();
- for _ in 0..10 {
- // shift values 1 step to the right by pop, sub one, push
- ring.pop_front();
- for elt in &mut ring {
- *elt -= 1;
- }
- ring.push_back(len - 1);
- }
-
- // try every shift
- for _ in 0..shifted.capacity() {
- shifted.pop_front();
- for elt in &mut shifted {
- *elt -= 1;
- }
- shifted.push_back(len - 1);
- assert_eq!(shifted, ring);
- assert_eq!(ring, shifted);
- }
-}
-
-#[test]
-fn test_ord() {
- let x = VecDeque::new();
- let mut y = VecDeque::new();
- y.push_back(1);
- y.push_back(2);
- y.push_back(3);
- assert!(x < y);
- assert!(y > x);
- assert!(x <= x);
- assert!(x >= x);
-}
-
-#[test]
-fn test_show() {
- let ringbuf: VecDeque<_> = (0..10).collect();
- assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
-
- let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"]
- .iter()
- .cloned()
- .collect();
- assert_eq!(format!("{:?}", ringbuf),
- "[\"just\", \"one\", \"test\", \"more\"]");
-}
-
-#[test]
-fn test_drop() {
- static mut DROPS: i32 = 0;
- struct Elem;
- impl Drop for Elem {
- fn drop(&mut self) {
- unsafe {
- DROPS += 1;
- }
- }
- }
-
- let mut ring = VecDeque::new();
- ring.push_back(Elem);
- ring.push_front(Elem);
- ring.push_back(Elem);
- ring.push_front(Elem);
- drop(ring);
-
- assert_eq!(unsafe { DROPS }, 4);
-}
-
-#[test]
-fn test_drop_with_pop() {
- static mut DROPS: i32 = 0;
- struct Elem;
- impl Drop for Elem {
- fn drop(&mut self) {
- unsafe {
- DROPS += 1;
- }
- }
- }
-
- let mut ring = VecDeque::new();
- ring.push_back(Elem);
- ring.push_front(Elem);
- ring.push_back(Elem);
- ring.push_front(Elem);
-
- drop(ring.pop_back());
- drop(ring.pop_front());
- assert_eq!(unsafe { DROPS }, 2);
-
- drop(ring);
- assert_eq!(unsafe { DROPS }, 4);
-}
-
-#[test]
-fn test_drop_clear() {
- static mut DROPS: i32 = 0;
- struct Elem;
- impl Drop for Elem {
- fn drop(&mut self) {
- unsafe {
- DROPS += 1;
- }
- }
- }
-
- let mut ring = VecDeque::new();
- ring.push_back(Elem);
- ring.push_front(Elem);
- ring.push_back(Elem);
- ring.push_front(Elem);
- ring.clear();
- assert_eq!(unsafe { DROPS }, 4);
-
- drop(ring);
- assert_eq!(unsafe { DROPS }, 4);
-}
-
-#[test]
-fn test_reserve_grow() {
- // test growth path A
- // [T o o H] -> [T o o H . . . . ]
- let mut ring = VecDeque::with_capacity(4);
- for i in 0..3 {
- ring.push_back(i);
- }
- ring.reserve(7);
- for i in 0..3 {
- assert_eq!(ring.pop_front(), Some(i));
- }
-
- // test growth path B
- // [H T o o] -> [. T o o H . . . ]
- let mut ring = VecDeque::with_capacity(4);
- for i in 0..1 {
- ring.push_back(i);
- assert_eq!(ring.pop_front(), Some(i));
- }
- for i in 0..3 {
- ring.push_back(i);
- }
- ring.reserve(7);
- for i in 0..3 {
- assert_eq!(ring.pop_front(), Some(i));
- }
-
- // test growth path C
- // [o o H T] -> [o o H . . . . T ]
- let mut ring = VecDeque::with_capacity(4);
- for i in 0..3 {
- ring.push_back(i);
- assert_eq!(ring.pop_front(), Some(i));
- }
- for i in 0..3 {
- ring.push_back(i);
- }
- ring.reserve(7);
- for i in 0..3 {
- assert_eq!(ring.pop_front(), Some(i));
- }
-}
-
-#[test]
-fn test_get() {
- let mut ring = VecDeque::new();
- ring.push_back(0);
- assert_eq!(ring.get(0), Some(&0));
- assert_eq!(ring.get(1), None);
-
- ring.push_back(1);
- assert_eq!(ring.get(0), Some(&0));
- assert_eq!(ring.get(1), Some(&1));
- assert_eq!(ring.get(2), None);
-
- ring.push_back(2);
- assert_eq!(ring.get(0), Some(&0));
- assert_eq!(ring.get(1), Some(&1));
- assert_eq!(ring.get(2), Some(&2));
- assert_eq!(ring.get(3), None);
-
- assert_eq!(ring.pop_front(), Some(0));
- assert_eq!(ring.get(0), Some(&1));
- assert_eq!(ring.get(1), Some(&2));
- assert_eq!(ring.get(2), None);
-
- assert_eq!(ring.pop_front(), Some(1));
- assert_eq!(ring.get(0), Some(&2));
- assert_eq!(ring.get(1), None);
-
- assert_eq!(ring.pop_front(), Some(2));
- assert_eq!(ring.get(0), None);
- assert_eq!(ring.get(1), None);
-}
-
-#[test]
-fn test_get_mut() {
- let mut ring = VecDeque::new();
- for i in 0..3 {
- ring.push_back(i);
- }
-
- match ring.get_mut(1) {
- Some(x) => *x = -1,
- None => (),
- };
-
- assert_eq!(ring.get_mut(0), Some(&mut 0));
- assert_eq!(ring.get_mut(1), Some(&mut -1));
- assert_eq!(ring.get_mut(2), Some(&mut 2));
- assert_eq!(ring.get_mut(3), None);
-
- assert_eq!(ring.pop_front(), Some(0));
- assert_eq!(ring.get_mut(0), Some(&mut -1));
- assert_eq!(ring.get_mut(1), Some(&mut 2));
- assert_eq!(ring.get_mut(2), None);
-}
-
-#[test]
-fn test_front() {
- let mut ring = VecDeque::new();
- ring.push_back(10);
- ring.push_back(20);
- assert_eq!(ring.front(), Some(&10));
- ring.pop_front();
- assert_eq!(ring.front(), Some(&20));
- ring.pop_front();
- assert_eq!(ring.front(), None);
-}
-
-#[test]
-fn test_as_slices() {
- let mut ring: VecDeque<i32> = VecDeque::with_capacity(127);
- let cap = ring.capacity() as i32;
- let first = cap / 2;
- let last = cap - first;
- for i in 0..first {
- ring.push_back(i);
-
- let (left, right) = ring.as_slices();
- let expected: Vec<_> = (0..i + 1).collect();
- assert_eq!(left, &expected[..]);
- assert_eq!(right, []);
- }
-
- for j in -last..0 {
- ring.push_front(j);
- let (left, right) = ring.as_slices();
- let expected_left: Vec<_> = (-last..j + 1).rev().collect();
- let expected_right: Vec<_> = (0..first).collect();
- assert_eq!(left, &expected_left[..]);
- assert_eq!(right, &expected_right[..]);
- }
-
- assert_eq!(ring.len() as i32, cap);
- assert_eq!(ring.capacity() as i32, cap);
-}
-
-#[test]
-fn test_as_mut_slices() {
- let mut ring: VecDeque<i32> = VecDeque::with_capacity(127);
- let cap = ring.capacity() as i32;
- let first = cap / 2;
- let last = cap - first;
- for i in 0..first {
- ring.push_back(i);
-
- let (left, right) = ring.as_mut_slices();
- let expected: Vec<_> = (0..i + 1).collect();
- assert_eq!(left, &expected[..]);
- assert_eq!(right, []);
- }
-
- for j in -last..0 {
- ring.push_front(j);
- let (left, right) = ring.as_mut_slices();
- let expected_left: Vec<_> = (-last..j + 1).rev().collect();
- let expected_right: Vec<_> = (0..first).collect();
- assert_eq!(left, &expected_left[..]);
- assert_eq!(right, &expected_right[..]);
- }
-
- assert_eq!(ring.len() as i32, cap);
- assert_eq!(ring.capacity() as i32, cap);
-}
-
-#[test]
-fn test_append() {
- let mut a: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
- let mut b: VecDeque<_> = vec![4, 5, 6].into_iter().collect();
-
- // normal append
- a.append(&mut b);
- assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
- assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []);
-
- // append nothing to something
- a.append(&mut b);
- assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
- assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []);
-
- // append something to nothing
- b.append(&mut a);
- assert_eq!(b.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
- assert_eq!(a.iter().cloned().collect::<Vec<_>>(), []);
-}
-
-#[test]
-fn test_retain() {
- let mut buf = VecDeque::new();
- buf.extend(1..5);
- buf.retain(|&x| x % 2 == 0);
- let v: Vec<_> = buf.into_iter().collect();
- assert_eq!(&v[..], &[2, 4]);
-}
-
-#[test]
-fn test_extend_ref() {
- let mut v = VecDeque::new();
- v.push_back(1);
- v.extend(&[2, 3, 4]);
-
- assert_eq!(v.len(), 4);
- assert_eq!(v[0], 1);
- assert_eq!(v[1], 2);
- assert_eq!(v[2], 3);
- assert_eq!(v[3], 4);
-
- let mut w = VecDeque::new();
- w.push_back(5);
- w.push_back(6);
- v.extend(&w);
-
- assert_eq!(v.len(), 6);
- assert_eq!(v[0], 1);
- assert_eq!(v[1], 2);
- assert_eq!(v[2], 3);
- assert_eq!(v[3], 4);
- assert_eq!(v[4], 5);
- assert_eq!(v[5], 6);
-}
-
-#[test]
-fn test_contains() {
- let mut v = VecDeque::new();
- v.extend(&[2, 3, 4]);
-
- assert!(v.contains(&3));
- assert!(!v.contains(&1));
-
- v.clear();
-
- assert!(!v.contains(&3));
-}
-
-#[allow(dead_code)]
-fn assert_covariance() {
- fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
- d
- }
-}
-
-#[test]
-fn test_is_empty() {
- let mut v = VecDeque::<i32>::new();
- assert!(v.is_empty());
- assert!(v.iter().is_empty());
- assert!(v.iter_mut().is_empty());
- v.extend(&[2, 3, 4]);
- assert!(!v.is_empty());
- assert!(!v.iter().is_empty());
- assert!(!v.iter_mut().is_empty());
- while let Some(_) = v.pop_front() {
- assert_eq!(v.is_empty(), v.len() == 0);
- assert_eq!(v.iter().is_empty(), v.iter().len() == 0);
- assert_eq!(v.iter_mut().is_empty(), v.iter_mut().len() == 0);
- }
- assert!(v.is_empty());
- assert!(v.iter().is_empty());
- assert!(v.iter_mut().is_empty());
- assert!(v.into_iter().is_empty());
-}
-
-#[test]
-fn test_placement_in() {
- let mut buf: VecDeque<isize> = VecDeque::new();
- buf.place_back() <- 1;
- buf.place_back() <- 2;
- assert_eq!(buf, [1,2]);
-
- buf.place_front() <- 3;
- buf.place_front() <- 4;
- assert_eq!(buf, [4,3,1,2]);
-
- {
- let ptr_head = buf.place_front() <- 5;
- assert_eq!(*ptr_head, 5);
- }
- {
- let ptr_tail = buf.place_back() <- 6;
- assert_eq!(*ptr_tail, 6);
- }
- assert_eq!(buf, [5,4,3,1,2,6]);
-}
bench = false
[[test]]
-name = "coretest"
-path = "../libcoretest/lib.rs"
+name = "coretests"
+path = "../libcore/tests/lib.rs"
[[bench]]
name = "corebenches"
// NOTE: The following code was generated by "src/etc/char_private.py",
// do not edit directly!
-use slice::SliceExt;
-
-fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
- for &s in singletons {
- if x == s {
- return false;
- } else if x < s {
+fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8],
+ normal: &[u8]) -> bool {
+ let xupper = (x >> 8) as u8;
+ let mut lowerstart = 0;
+ for &(upper, lowercount) in singletonuppers {
+ let lowerend = lowerstart + lowercount as usize;
+ if xupper == upper {
+ for &lower in &singletonlowers[lowerstart..lowerend] {
+ if lower == x as u8 {
+ return false;
+ }
+ }
+ } else if xupper < upper {
break;
}
+ lowerstart = lowerend;
}
- for w in normal.chunks(2) {
- let start = w[0];
- let len = w[1];
- let difference = (x as i32) - (start as i32);
- if 0 <= difference {
- if difference < len as i32 {
- return false;
- }
+
+ let mut x = x as i32;
+ let mut normal = normal.iter().cloned();
+ let mut current = true;
+ while let Some(v) = normal.next() {
+ let len = if v & 0x80 != 0 {
+ ((v & 0x7f) as i32) << 8 | normal.next().unwrap() as i32
} else {
+ v as i32
+ };
+ x -= len;
+ if x < 0 {
break;
}
+ current = !current;
}
- true
+ current
}
pub fn is_printable(x: char) -> bool {
let x = x as u32;
let lower = x as u16;
if x < 0x10000 {
- check(lower, SINGLETONS0, NORMAL0)
+ check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0)
} else if x < 0x20000 {
- check(lower, SINGLETONS1, NORMAL1)
+ check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1)
} else {
if 0x2a6d7 <= x && x < 0x2a700 {
return false;
}
}
-const SINGLETONS0: &'static [u16] = &[
- 0xad,
- 0x378,
- 0x379,
- 0x38b,
- 0x38d,
- 0x3a2,
- 0x530,
- 0x557,
- 0x558,
- 0x560,
- 0x588,
- 0x58b,
- 0x58c,
- 0x590,
- 0x61c,
- 0x61d,
- 0x6dd,
- 0x70e,
- 0x70f,
- 0x74b,
- 0x74c,
- 0x82e,
- 0x82f,
- 0x83f,
- 0x85c,
- 0x85d,
- 0x8b5,
- 0x8e2,
- 0x984,
- 0x98d,
- 0x98e,
- 0x991,
- 0x992,
- 0x9a9,
- 0x9b1,
- 0x9ba,
- 0x9bb,
- 0x9c5,
- 0x9c6,
- 0x9c9,
- 0x9ca,
- 0x9de,
- 0x9e4,
- 0x9e5,
- 0xa04,
- 0xa11,
- 0xa12,
- 0xa29,
- 0xa31,
- 0xa34,
- 0xa37,
- 0xa3a,
- 0xa3b,
- 0xa3d,
- 0xa49,
- 0xa4a,
- 0xa5d,
- 0xa84,
- 0xa8e,
- 0xa92,
- 0xaa9,
- 0xab1,
- 0xab4,
- 0xaba,
- 0xabb,
- 0xac6,
- 0xaca,
- 0xace,
- 0xacf,
- 0xae4,
- 0xae5,
- 0xb04,
- 0xb0d,
- 0xb0e,
- 0xb11,
- 0xb12,
- 0xb29,
- 0xb31,
- 0xb34,
- 0xb3a,
- 0xb3b,
- 0xb45,
- 0xb46,
- 0xb49,
- 0xb4a,
- 0xb5e,
- 0xb64,
- 0xb65,
- 0xb84,
- 0xb91,
- 0xb9b,
- 0xb9d,
- 0xbc9,
- 0xbce,
- 0xbcf,
- 0xc04,
- 0xc0d,
- 0xc11,
- 0xc29,
- 0xc45,
- 0xc49,
- 0xc57,
- 0xc64,
- 0xc65,
- 0xc84,
- 0xc8d,
- 0xc91,
- 0xca9,
- 0xcb4,
- 0xcba,
- 0xcbb,
- 0xcc5,
- 0xcc9,
- 0xcdf,
- 0xce4,
- 0xce5,
- 0xcf0,
- 0xd04,
- 0xd0d,
- 0xd11,
- 0xd3b,
- 0xd3c,
- 0xd45,
- 0xd49,
- 0xd64,
- 0xd65,
- 0xd80,
- 0xd81,
- 0xd84,
- 0xdb2,
- 0xdbc,
- 0xdbe,
- 0xdbf,
- 0xdd5,
- 0xdd7,
- 0xdf0,
- 0xdf1,
- 0xe83,
- 0xe85,
- 0xe86,
- 0xe89,
- 0xe8b,
- 0xe8c,
- 0xe98,
- 0xea0,
- 0xea4,
- 0xea6,
- 0xea8,
- 0xea9,
- 0xeac,
- 0xeba,
- 0xebe,
- 0xebf,
- 0xec5,
- 0xec7,
- 0xece,
- 0xecf,
- 0xeda,
- 0xedb,
- 0xf48,
- 0xf98,
- 0xfbd,
- 0xfcd,
- 0x10c6,
- 0x10ce,
- 0x10cf,
- 0x1249,
- 0x124e,
- 0x124f,
- 0x1257,
- 0x1259,
- 0x125e,
- 0x125f,
- 0x1289,
- 0x128e,
- 0x128f,
- 0x12b1,
- 0x12b6,
- 0x12b7,
- 0x12bf,
- 0x12c1,
- 0x12c6,
- 0x12c7,
- 0x12d7,
- 0x1311,
- 0x1316,
- 0x1317,
- 0x135b,
- 0x135c,
- 0x13f6,
- 0x13f7,
- 0x13fe,
- 0x13ff,
- 0x1680,
- 0x170d,
- 0x176d,
- 0x1771,
- 0x17de,
- 0x17df,
- 0x180e,
- 0x180f,
- 0x191f,
- 0x196e,
- 0x196f,
- 0x1a1c,
- 0x1a1d,
- 0x1a5f,
- 0x1a7d,
- 0x1a7e,
- 0x1aae,
- 0x1aaf,
- 0x1cf7,
- 0x1f16,
- 0x1f17,
- 0x1f1e,
- 0x1f1f,
- 0x1f46,
- 0x1f47,
- 0x1f4e,
- 0x1f4f,
- 0x1f58,
- 0x1f5a,
- 0x1f5c,
- 0x1f5e,
- 0x1f7e,
- 0x1f7f,
- 0x1fb5,
- 0x1fc5,
- 0x1fd4,
- 0x1fd5,
- 0x1fdc,
- 0x1ff0,
- 0x1ff1,
- 0x1ff5,
- 0x2072,
- 0x2073,
- 0x208f,
- 0x23ff,
- 0x2b74,
- 0x2b75,
- 0x2b96,
- 0x2b97,
- 0x2bc9,
- 0x2c2f,
- 0x2c5f,
- 0x2d26,
- 0x2d2e,
- 0x2d2f,
- 0x2da7,
- 0x2daf,
- 0x2db7,
- 0x2dbf,
- 0x2dc7,
- 0x2dcf,
- 0x2dd7,
- 0x2ddf,
- 0x2e9a,
- 0x3040,
- 0x3097,
- 0x3098,
- 0x318f,
- 0x321f,
- 0x32ff,
- 0xa7af,
- 0xa8fe,
- 0xa8ff,
- 0xa9ce,
- 0xa9ff,
- 0xaa4e,
- 0xaa4f,
- 0xaa5a,
- 0xaa5b,
- 0xab07,
- 0xab08,
- 0xab0f,
- 0xab10,
- 0xab27,
- 0xab2f,
- 0xabee,
- 0xabef,
- 0xfa6e,
- 0xfa6f,
- 0xfb37,
- 0xfb3d,
- 0xfb3f,
- 0xfb42,
- 0xfb45,
- 0xfd90,
- 0xfd91,
- 0xfdfe,
- 0xfdff,
- 0xfe53,
- 0xfe67,
- 0xfe75,
- 0xffc8,
- 0xffc9,
- 0xffd0,
- 0xffd1,
- 0xffd8,
- 0xffd9,
- 0xffe7,
- 0xfffe,
- 0xffff,
+const SINGLETONS0U: &'static [(u8, u8)] = &[
+ (0x00, 1),
+ (0x03, 5),
+ (0x05, 8),
+ (0x06, 3),
+ (0x07, 4),
+ (0x08, 7),
+ (0x09, 16),
+ (0x0a, 27),
+ (0x0b, 24),
+ (0x0c, 22),
+ (0x0d, 20),
+ (0x0e, 22),
+ (0x0f, 4),
+ (0x10, 3),
+ (0x12, 18),
+ (0x13, 9),
+ (0x16, 1),
+ (0x17, 5),
+ (0x18, 2),
+ (0x19, 3),
+ (0x1a, 7),
+ (0x1c, 1),
+ (0x1f, 22),
+ (0x20, 3),
+ (0x23, 1),
+ (0x2b, 5),
+ (0x2c, 2),
+ (0x2d, 11),
+ (0x2e, 1),
+ (0x30, 3),
+ (0x31, 1),
+ (0x32, 2),
+ (0xa7, 1),
+ (0xa8, 2),
+ (0xa9, 2),
+ (0xaa, 4),
+ (0xab, 8),
+ (0xfa, 2),
+ (0xfb, 5),
+ (0xfd, 4),
+ (0xfe, 3),
+ (0xff, 9),
];
-const SINGLETONS1: &'static [u16] = &[
- 0xc,
- 0x27,
- 0x3b,
- 0x3e,
- 0x4e,
- 0x4f,
- 0x18f,
- 0x39e,
- 0x49e,
- 0x49f,
- 0x806,
- 0x807,
- 0x809,
- 0x836,
- 0x83d,
- 0x83e,
- 0x856,
- 0x8f3,
- 0x9d0,
- 0x9d1,
- 0xa04,
- 0xa14,
- 0xa18,
- 0xb56,
- 0xb57,
- 0x10bd,
- 0x1135,
- 0x11ce,
- 0x11cf,
- 0x11e0,
- 0x1212,
- 0x1287,
- 0x1289,
- 0x128e,
- 0x129e,
- 0x1304,
- 0x130d,
- 0x130e,
- 0x1311,
- 0x1312,
- 0x1329,
- 0x1331,
- 0x1334,
- 0x133a,
- 0x133b,
- 0x1345,
- 0x1346,
- 0x1349,
- 0x134a,
- 0x134e,
- 0x134f,
- 0x1364,
- 0x1365,
- 0x145a,
- 0x145c,
- 0x15b6,
- 0x15b7,
- 0x1c09,
- 0x1c37,
- 0x1c90,
- 0x1c91,
- 0x1ca8,
- 0x246f,
- 0x6a5f,
- 0x6aee,
- 0x6aef,
- 0x6b5a,
- 0x6b62,
- 0xbc9a,
- 0xbc9b,
- 0xd127,
- 0xd128,
- 0xd455,
- 0xd49d,
- 0xd4a0,
- 0xd4a1,
- 0xd4a3,
- 0xd4a4,
- 0xd4a7,
- 0xd4a8,
- 0xd4ad,
- 0xd4ba,
- 0xd4bc,
- 0xd4c4,
- 0xd506,
- 0xd50b,
- 0xd50c,
- 0xd515,
- 0xd51d,
- 0xd53a,
- 0xd53f,
- 0xd545,
- 0xd551,
- 0xd6a6,
- 0xd6a7,
- 0xd7cc,
- 0xd7cd,
- 0xdaa0,
- 0xe007,
- 0xe019,
- 0xe01a,
- 0xe022,
- 0xe025,
- 0xe8c5,
- 0xe8c6,
- 0xee04,
- 0xee20,
- 0xee23,
- 0xee25,
- 0xee26,
- 0xee28,
- 0xee33,
- 0xee38,
- 0xee3a,
- 0xee48,
- 0xee4a,
- 0xee4c,
- 0xee50,
- 0xee53,
- 0xee55,
- 0xee56,
- 0xee58,
- 0xee5a,
- 0xee5c,
- 0xee5e,
- 0xee60,
- 0xee63,
- 0xee65,
- 0xee66,
- 0xee6b,
- 0xee73,
- 0xee78,
- 0xee7d,
- 0xee7f,
- 0xee8a,
- 0xeea4,
- 0xeeaa,
- 0xf0af,
- 0xf0b0,
- 0xf0c0,
- 0xf0d0,
- 0xf12f,
- 0xf91f,
- 0xf931,
- 0xf932,
- 0xf93f,
+const SINGLETONS0L: &'static [u8] = &[
+ 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57,
+ 0x58, 0x60, 0x88, 0x8b, 0x8c, 0x90, 0x1c, 0x1d,
+ 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0x2e, 0x2f, 0x3f,
+ 0x5c, 0x5d, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91,
+ 0x92, 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6, 0xc9,
+ 0xca, 0xde, 0xe4, 0xe5, 0x04, 0x11, 0x12, 0x29,
+ 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a,
+ 0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba,
+ 0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5, 0x04,
+ 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
+ 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65,
+ 0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce, 0xcf, 0x04,
+ 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65,
+ 0x84, 0x8d, 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5,
+ 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04, 0x0d, 0x11,
+ 0x3b, 0x3c, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81,
+ 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0,
+ 0xf1, 0x83, 0x85, 0x86, 0x89, 0x8b, 0x8c, 0x98,
+ 0xa0, 0xa4, 0xa6, 0xa8, 0xa9, 0xac, 0xba, 0xbe,
+ 0xbf, 0xc5, 0xc7, 0xce, 0xcf, 0xda, 0xdb, 0x48,
+ 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, 0x4e,
+ 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f,
+ 0xb1, 0xb6, 0xb7, 0xbf, 0xc1, 0xc6, 0xc7, 0xd7,
+ 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe,
+ 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e,
+ 0x0f, 0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d,
+ 0x7e, 0xae, 0xaf, 0xf7, 0x16, 0x17, 0x1e, 0x1f,
+ 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e,
+ 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0,
+ 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0xff, 0x74, 0x75,
+ 0x96, 0x97, 0xc9, 0x2f, 0x5f, 0x26, 0x2e, 0x2f,
+ 0xa7, 0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf,
+ 0x9a, 0x40, 0x97, 0x98, 0x8f, 0x1f, 0xff, 0xaf,
+ 0xfe, 0xff, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b,
+ 0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f, 0xee, 0xef,
+ 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90,
+ 0x91, 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9,
+ 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff,
];
-const NORMAL0: &'static [u16] = &[
- 0x0, 0x20,
- 0x7f, 0x22,
- 0x380, 0x4,
- 0x5c8, 0x8,
- 0x5eb, 0x5,
- 0x5f5, 0x11,
- 0x7b2, 0xe,
- 0x7fb, 0x5,
- 0x85f, 0x41,
- 0x8be, 0x16,
- 0x9b3, 0x3,
- 0x9cf, 0x8,
- 0x9d8, 0x4,
- 0x9fc, 0x5,
- 0xa0b, 0x4,
- 0xa43, 0x4,
- 0xa4e, 0x3,
- 0xa52, 0x7,
- 0xa5f, 0x7,
- 0xa76, 0xb,
- 0xad1, 0xf,
- 0xaf2, 0x7,
- 0xafa, 0x7,
- 0xb4e, 0x8,
- 0xb58, 0x4,
- 0xb78, 0xa,
- 0xb8b, 0x3,
- 0xb96, 0x3,
- 0xba0, 0x3,
- 0xba5, 0x3,
- 0xbab, 0x3,
- 0xbba, 0x4,
- 0xbc3, 0x3,
- 0xbd1, 0x6,
- 0xbd8, 0xe,
- 0xbfb, 0x5,
- 0xc3a, 0x3,
- 0xc4e, 0x7,
- 0xc5b, 0x5,
- 0xc70, 0x8,
- 0xcce, 0x7,
- 0xcd7, 0x7,
- 0xcf3, 0xe,
- 0xd50, 0x4,
- 0xd97, 0x3,
- 0xdc7, 0x3,
- 0xdcb, 0x4,
- 0xde0, 0x6,
- 0xdf5, 0xc,
- 0xe3b, 0x4,
- 0xe5c, 0x25,
- 0xe8e, 0x6,
- 0xee0, 0x20,
- 0xf6d, 0x4,
- 0xfdb, 0x25,
- 0x10c8, 0x5,
- 0x137d, 0x3,
- 0x139a, 0x6,
- 0x169d, 0x3,
- 0x16f9, 0x7,
- 0x1715, 0xb,
- 0x1737, 0x9,
- 0x1754, 0xc,
- 0x1774, 0xc,
- 0x17ea, 0x6,
- 0x17fa, 0x6,
- 0x181a, 0x6,
- 0x1878, 0x8,
- 0x18ab, 0x5,
- 0x18f6, 0xa,
- 0x192c, 0x4,
- 0x193c, 0x4,
- 0x1941, 0x3,
- 0x1975, 0xb,
- 0x19ac, 0x4,
- 0x19ca, 0x6,
- 0x19db, 0x3,
- 0x1a8a, 0x6,
- 0x1a9a, 0x6,
- 0x1abf, 0x41,
- 0x1b4c, 0x4,
- 0x1b7d, 0x3,
- 0x1bf4, 0x8,
- 0x1c38, 0x3,
- 0x1c4a, 0x3,
- 0x1c89, 0x37,
- 0x1cc8, 0x8,
- 0x1cfa, 0x6,
- 0x1df6, 0x5,
- 0x1fff, 0x11,
- 0x2028, 0x8,
- 0x205f, 0x11,
- 0x209d, 0x3,
- 0x20bf, 0x11,
- 0x20f1, 0xf,
- 0x218c, 0x4,
- 0x2427, 0x19,
- 0x244b, 0x15,
- 0x2bba, 0x3,
- 0x2bd2, 0x1a,
- 0x2bf0, 0x10,
- 0x2cf4, 0x5,
- 0x2d28, 0x5,
- 0x2d68, 0x7,
- 0x2d71, 0xe,
- 0x2d97, 0x9,
- 0x2e45, 0x3b,
- 0x2ef4, 0xc,
- 0x2fd6, 0x1a,
- 0x2ffc, 0x5,
- 0x3100, 0x5,
- 0x312e, 0x3,
- 0x31bb, 0x5,
- 0x31e4, 0xc,
- 0x4db6, 0xa,
- 0x9fd6, 0x2a,
- 0xa48d, 0x3,
- 0xa4c7, 0x9,
- 0xa62c, 0x14,
- 0xa6f8, 0x8,
- 0xa7b8, 0x3f,
- 0xa82c, 0x4,
- 0xa83a, 0x6,
- 0xa878, 0x8,
- 0xa8c6, 0x8,
- 0xa8da, 0x6,
- 0xa954, 0xb,
- 0xa97d, 0x3,
- 0xa9da, 0x4,
- 0xaa37, 0x9,
- 0xaac3, 0x18,
- 0xaaf7, 0xa,
- 0xab17, 0x9,
- 0xab66, 0xa,
- 0xabfa, 0x6,
- 0xd7a4, 0xc,
- 0xd7c7, 0x4,
- 0xd7fc, 0x2104,
- 0xfada, 0x26,
- 0xfb07, 0xc,
- 0xfb18, 0x5,
- 0xfbc2, 0x11,
- 0xfd40, 0x10,
- 0xfdc8, 0x28,
- 0xfe1a, 0x6,
- 0xfe6c, 0x4,
- 0xfefd, 0x4,
- 0xffbf, 0x3,
- 0xffdd, 0x3,
- 0xffef, 0xd,
+const SINGLETONS1U: &'static [(u8, u8)] = &[
+ (0x00, 6),
+ (0x01, 1),
+ (0x03, 1),
+ (0x04, 2),
+ (0x08, 8),
+ (0x09, 2),
+ (0x0a, 3),
+ (0x0b, 2),
+ (0x10, 1),
+ (0x11, 4),
+ (0x12, 5),
+ (0x13, 18),
+ (0x14, 2),
+ (0x15, 2),
+ (0x1c, 5),
+ (0x24, 1),
+ (0x6a, 3),
+ (0x6b, 2),
+ (0xbc, 2),
+ (0xd1, 2),
+ (0xd4, 12),
+ (0xd5, 9),
+ (0xd6, 2),
+ (0xd7, 2),
+ (0xda, 1),
+ (0xe0, 5),
+ (0xe8, 2),
+ (0xee, 32),
+ (0xf0, 4),
+ (0xf1, 1),
+ (0xf9, 4),
];
-const NORMAL1: &'static [u16] = &[
+const SINGLETONS1L: &'static [u8] = &[
+ 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e,
+ 0x9e, 0x9f, 0x06, 0x07, 0x09, 0x36, 0x3d, 0x3e,
+ 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x56,
+ 0x57, 0xbd, 0x35, 0xce, 0xcf, 0xe0, 0x12, 0x87,
+ 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12,
+ 0x29, 0x31, 0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49,
+ 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5a, 0x5c, 0xb6,
+ 0xb7, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x6f, 0x5f,
+ 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28,
+ 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8,
+ 0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15,
+ 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc,
+ 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0xc5,
+ 0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33,
+ 0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55,
+ 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65,
+ 0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4,
+ 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0x2f, 0x1f, 0x31,
+ 0x32, 0x3f,
+];
+const NORMAL0: &'static [u8] = &[
+ 0x00, 0x20,
+ 0x5f, 0x22,
+ 0x82, 0xdf, 0x04,
+ 0x82, 0x44, 0x08,
+ 0x1b, 0x05,
+ 0x05, 0x11,
+ 0x81, 0xac, 0x0e,
+ 0x3b, 0x05,
+ 0x5f, 0x41,
+ 0x1e, 0x16,
+ 0x80, 0xdf, 0x03,
+ 0x19, 0x08,
+ 0x01, 0x04,
+ 0x20, 0x05,
+ 0x0a, 0x04,
+ 0x34, 0x04,
+ 0x07, 0x03,
+ 0x01, 0x07,
+ 0x06, 0x07,
+ 0x10, 0x0b,
+ 0x50, 0x0f,
+ 0x12, 0x07,
+ 0x01, 0x07,
+ 0x4d, 0x08,
+ 0x02, 0x04,
+ 0x1c, 0x0a,
+ 0x09, 0x03,
+ 0x08, 0x03,
+ 0x07, 0x03,
+ 0x02, 0x03,
+ 0x03, 0x03,
+ 0x0c, 0x04,
+ 0x05, 0x03,
+ 0x0b, 0x06,
+ 0x01, 0x0e,
+ 0x15, 0x05,
+ 0x3a, 0x03,
+ 0x11, 0x07,
+ 0x06, 0x05,
+ 0x10, 0x08,
+ 0x56, 0x07,
+ 0x02, 0x07,
+ 0x15, 0x0e,
+ 0x4f, 0x04,
+ 0x43, 0x03,
+ 0x2d, 0x03,
+ 0x01, 0x04,
+ 0x11, 0x06,
+ 0x0f, 0x0c,
+ 0x3a, 0x04,
+ 0x1d, 0x25,
+ 0x0d, 0x06,
+ 0x4c, 0x20,
+ 0x6d, 0x04,
+ 0x6a, 0x25,
+ 0x80, 0xc8, 0x05,
+ 0x82, 0xb0, 0x03,
+ 0x1a, 0x06,
+ 0x82, 0xfd, 0x03,
+ 0x59, 0x07,
+ 0x15, 0x0b,
+ 0x17, 0x09,
+ 0x14, 0x0c,
+ 0x14, 0x0c,
+ 0x6a, 0x06,
+ 0x0a, 0x06,
+ 0x1a, 0x06,
+ 0x58, 0x08,
+ 0x2b, 0x05,
+ 0x46, 0x0a,
+ 0x2c, 0x04,
+ 0x0c, 0x04,
+ 0x01, 0x03,
+ 0x31, 0x0b,
+ 0x2c, 0x04,
+ 0x1a, 0x06,
+ 0x0b, 0x03,
+ 0x80, 0xac, 0x06,
+ 0x0a, 0x06,
+ 0x1f, 0x41,
+ 0x4c, 0x04,
+ 0x2d, 0x03,
+ 0x74, 0x08,
+ 0x3c, 0x03,
+ 0x0f, 0x03,
+ 0x3c, 0x37,
+ 0x08, 0x08,
+ 0x2a, 0x06,
+ 0x80, 0xf6, 0x05,
+ 0x82, 0x04, 0x11,
+ 0x18, 0x08,
+ 0x2f, 0x11,
+ 0x2d, 0x03,
+ 0x1f, 0x11,
+ 0x21, 0x0f,
+ 0x80, 0x8c, 0x04,
+ 0x82, 0x97, 0x19,
+ 0x0b, 0x15,
+ 0x87, 0x5a, 0x03,
+ 0x15, 0x1a,
+ 0x04, 0x10,
+ 0x80, 0xf4, 0x05,
+ 0x2f, 0x05,
+ 0x3b, 0x07,
+ 0x02, 0x0e,
+ 0x18, 0x09,
+ 0x80, 0xa5, 0x3b,
+ 0x74, 0x0c,
+ 0x80, 0xd6, 0x1a,
+ 0x0c, 0x05,
+ 0x80, 0xff, 0x05,
+ 0x29, 0x03,
+ 0x80, 0x8a, 0x05,
+ 0x24, 0x0c,
+ 0x9b, 0xc6, 0x0a,
+ 0xd2, 0x16, 0x2a,
+ 0x84, 0x8d, 0x03,
+ 0x37, 0x09,
+ 0x81, 0x5c, 0x14,
+ 0x80, 0xb8, 0x08,
+ 0x80, 0xb8, 0x3f,
+ 0x35, 0x04,
+ 0x0a, 0x06,
+ 0x38, 0x08,
+ 0x46, 0x08,
+ 0x0c, 0x06,
+ 0x74, 0x0b,
+ 0x1e, 0x03,
+ 0x5a, 0x04,
+ 0x59, 0x09,
+ 0x80, 0x83, 0x18,
+ 0x1c, 0x0a,
+ 0x16, 0x09,
+ 0x46, 0x0a,
+ 0x80, 0x8a, 0x06,
+ 0xab, 0xa4, 0x0c,
+ 0x17, 0x04,
+ 0x31, 0xa1, 0x04,
+ 0x81, 0xda, 0x26,
+ 0x07, 0x0c,
+ 0x05, 0x05,
+ 0x80, 0xa5, 0x11,
+ 0x81, 0x6d, 0x10,
+ 0x78, 0x28,
+ 0x2a, 0x06,
+ 0x4c, 0x04,
+ 0x80, 0x8d, 0x04,
+ 0x80, 0xbe, 0x03,
+ 0x1b, 0x03,
+ 0x0f, 0x0d,
+];
+const NORMAL1: &'static [u8] = &[
+ 0x5e, 0x22,
+ 0x7b, 0x05,
+ 0x03, 0x04,
+ 0x2d, 0x03,
+ 0x65, 0x04,
+ 0x01, 0x2f,
+ 0x2e, 0x80, 0x82,
+ 0x1d, 0x03,
+ 0x31, 0x0f,
+ 0x1c, 0x04,
+ 0x24, 0x0c,
+ 0x1b, 0x05,
+ 0x2b, 0x05,
+ 0x44, 0x04,
+ 0x0e, 0x2a,
+ 0x80, 0xaa, 0x06,
+ 0x24, 0x04,
+ 0x24, 0x04,
+ 0x28, 0x08,
+ 0x34, 0x0b,
+ 0x01, 0x80, 0x90,
+ 0x81, 0x37, 0x09,
+ 0x16, 0x0a,
+ 0x08, 0x80, 0x98,
+ 0x39, 0x03,
+ 0x63, 0x08,
+ 0x09, 0x30,
+ 0x16, 0x05,
+ 0x21, 0x03,
+ 0x1b, 0x05,
+ 0x01, 0x40,
+ 0x38, 0x04,
+ 0x4b, 0x05,
+ 0x28, 0x04,
+ 0x03, 0x04,
+ 0x09, 0x08,
+ 0x09, 0x07,
+ 0x40, 0x20,
+ 0x27, 0x04,
+ 0x0c, 0x09,
+ 0x36, 0x03,
+ 0x3a, 0x05,
+ 0x1a, 0x07,
+ 0x04, 0x0c,
+ 0x07, 0x50,
+ 0x49, 0x37,
+ 0x33, 0x0d,
+ 0x33, 0x07,
+ 0x06, 0x81, 0x60,
+ 0x1f, 0x81, 0x81,
+ 0x4e, 0x04,
+ 0x1e, 0x0f,
+ 0x43, 0x0e,
+ 0x19, 0x07,
+ 0x0a, 0x06,
+ 0x44, 0x0c,
+ 0x27, 0x09,
+ 0x75, 0x0b,
+ 0x3f, 0x41,
+ 0x2a, 0x06,
+ 0x3b, 0x05,
+ 0x0a, 0x06,
+ 0x51, 0x06,
+ 0x01, 0x05,
+ 0x10, 0x03,
+ 0x05, 0x80, 0x8b,
+ 0x5e, 0x22,
+ 0x48, 0x08,
+ 0x0a, 0x80, 0xa6,
0x5e, 0x22,
- 0xfb, 0x5,
- 0x103, 0x4,
- 0x134, 0x3,
- 0x19c, 0x4,
- 0x1a1, 0x2f,
- 0x1fe, 0x82,
- 0x29d, 0x3,
- 0x2d1, 0xf,
- 0x2fc, 0x4,
- 0x324, 0xc,
- 0x34b, 0x5,
- 0x37b, 0x5,
- 0x3c4, 0x4,
- 0x3d6, 0x2a,
- 0x4aa, 0x6,
- 0x4d4, 0x4,
- 0x4fc, 0x4,
- 0x528, 0x8,
- 0x564, 0xb,
- 0x570, 0x90,
- 0x737, 0x9,
- 0x756, 0xa,
- 0x768, 0x98,
- 0x839, 0x3,
- 0x89f, 0x8,
- 0x8b0, 0x30,
- 0x8f6, 0x5,
- 0x91c, 0x3,
- 0x93a, 0x5,
- 0x940, 0x40,
- 0x9b8, 0x4,
- 0xa07, 0x5,
- 0xa34, 0x4,
- 0xa3b, 0x4,
- 0xa48, 0x8,
- 0xa59, 0x7,
- 0xaa0, 0x20,
- 0xae7, 0x4,
- 0xaf7, 0x9,
- 0xb36, 0x3,
- 0xb73, 0x5,
- 0xb92, 0x7,
- 0xb9d, 0xc,
- 0xbb0, 0x50,
- 0xc49, 0x37,
- 0xcb3, 0xd,
- 0xcf3, 0x7,
- 0xd00, 0x160,
- 0xe7f, 0x181,
- 0x104e, 0x4,
- 0x1070, 0xf,
- 0x10c2, 0xe,
- 0x10e9, 0x7,
- 0x10fa, 0x6,
- 0x1144, 0xc,
- 0x1177, 0x9,
- 0x11f5, 0xb,
- 0x123f, 0x41,
- 0x12aa, 0x6,
- 0x12eb, 0x5,
- 0x12fa, 0x6,
- 0x1351, 0x6,
- 0x1358, 0x5,
- 0x136d, 0x3,
- 0x1375, 0x8b,
- 0x145e, 0x22,
- 0x14c8, 0x8,
- 0x14da, 0xa6,
- 0x15de, 0x22,
- 0x1645, 0xb,
- 0x165a, 0x6,
- 0x166d, 0x13,
- 0x16b8, 0x8,
- 0x16ca, 0x36,
- 0x171a, 0x3,
- 0x172c, 0x4,
- 0x1740, 0x160,
- 0x18f3, 0xc,
- 0x1900, 0x1c0,
- 0x1af9, 0x107,
- 0x1c46, 0xa,
- 0x1c6d, 0x3,
- 0x1cb7, 0x349,
- 0x239a, 0x66,
- 0x2475, 0xb,
- 0x2544, 0xabc,
- 0x342f, 0xfd1,
- 0x4647, 0x21b9,
- 0x6a39, 0x7,
- 0x6a6a, 0x4,
- 0x6a70, 0x60,
- 0x6af6, 0xa,
- 0x6b46, 0xa,
- 0x6b78, 0x5,
- 0x6b90, 0x370,
- 0x6f45, 0xb,
- 0x6f7f, 0x10,
- 0x6fa0, 0x40,
- 0x6fe1, 0x1f,
- 0x87ed, 0x13,
- 0x8af3, 0x250d,
- 0xb002, 0xbfe,
- 0xbc6b, 0x5,
- 0xbc7d, 0x3,
- 0xbc89, 0x7,
- 0xbca0, 0x1360,
- 0xd0f6, 0xa,
- 0xd173, 0x8,
- 0xd1e9, 0x17,
- 0xd246, 0xba,
- 0xd357, 0x9,
- 0xd372, 0x8e,
- 0xd547, 0x3,
- 0xda8c, 0xf,
- 0xdab0, 0x550,
- 0xe02b, 0x7d5,
- 0xe8d7, 0x29,
- 0xe94b, 0x5,
- 0xe95a, 0x4,
- 0xe960, 0x4a0,
- 0xee3c, 0x6,
- 0xee43, 0x4,
- 0xee9c, 0x5,
- 0xeebc, 0x34,
- 0xeef2, 0x10e,
- 0xf02c, 0x4,
- 0xf094, 0xc,
- 0xf0f6, 0xa,
- 0xf10d, 0x3,
- 0xf16c, 0x4,
- 0xf1ad, 0x39,
- 0xf203, 0xd,
- 0xf23c, 0x4,
- 0xf249, 0x7,
- 0xf252, 0xae,
- 0xf6d3, 0xd,
- 0xf6ed, 0x3,
- 0xf6f7, 0x9,
- 0xf774, 0xc,
- 0xf7d5, 0x2b,
- 0xf80c, 0x4,
- 0xf848, 0x8,
- 0xf85a, 0x6,
- 0xf888, 0x8,
- 0xf8ae, 0x62,
- 0xf928, 0x8,
- 0xf94c, 0x4,
- 0xf95f, 0x21,
- 0xf992, 0x2e,
- 0xf9c1, 0x63f,
+ 0x45, 0x0b,
+ 0x0a, 0x06,
+ 0x0d, 0x13,
+ 0x38, 0x08,
+ 0x0a, 0x36,
+ 0x1a, 0x03,
+ 0x0f, 0x04,
+ 0x10, 0x81, 0x60,
+ 0x53, 0x0c,
+ 0x01, 0x81, 0xc0,
+ 0x39, 0x81, 0x07,
+ 0x46, 0x0a,
+ 0x1d, 0x03,
+ 0x47, 0x83, 0x49,
+ 0x83, 0x9a, 0x66,
+ 0x75, 0x0b,
+ 0x80, 0xc4, 0x8a, 0xbc,
+ 0x84, 0x2f, 0x8f, 0xd1,
+ 0x82, 0x47, 0xa1, 0xb9,
+ 0x82, 0x39, 0x07,
+ 0x2a, 0x04,
+ 0x02, 0x60,
+ 0x26, 0x0a,
+ 0x46, 0x0a,
+ 0x28, 0x05,
+ 0x13, 0x83, 0x70,
+ 0x45, 0x0b,
+ 0x2f, 0x10,
+ 0x11, 0x40,
+ 0x01, 0x1f,
+ 0x97, 0xed, 0x13,
+ 0x82, 0xf3, 0xa5, 0x0d,
+ 0x02, 0x8b, 0xfe,
+ 0x6b, 0x05,
+ 0x0d, 0x03,
+ 0x09, 0x07,
+ 0x10, 0x93, 0x60,
+ 0x80, 0xf6, 0x0a,
+ 0x73, 0x08,
+ 0x6e, 0x17,
+ 0x46, 0x80, 0xba,
+ 0x57, 0x09,
+ 0x12, 0x80, 0x8e,
+ 0x81, 0x47, 0x03,
+ 0x85, 0x42, 0x0f,
+ 0x15, 0x85, 0x50,
+ 0x2b, 0x87, 0xd5,
+ 0x80, 0xd7, 0x29,
+ 0x4b, 0x05,
+ 0x0a, 0x04,
+ 0x02, 0x84, 0xa0,
+ 0x3c, 0x06,
+ 0x01, 0x04,
+ 0x55, 0x05,
+ 0x1b, 0x34,
+ 0x02, 0x81, 0x0e,
+ 0x2c, 0x04,
+ 0x64, 0x0c,
+ 0x56, 0x0a,
+ 0x0d, 0x03,
+ 0x5c, 0x04,
+ 0x3d, 0x39,
+ 0x1d, 0x0d,
+ 0x2c, 0x04,
+ 0x09, 0x07,
+ 0x02, 0x80, 0xae,
+ 0x83, 0xd3, 0x0d,
+ 0x0d, 0x03,
+ 0x07, 0x09,
+ 0x74, 0x0c,
+ 0x55, 0x2b,
+ 0x0c, 0x04,
+ 0x38, 0x08,
+ 0x0a, 0x06,
+ 0x28, 0x08,
+ 0x1e, 0x62,
+ 0x18, 0x08,
+ 0x1c, 0x04,
+ 0x0f, 0x21,
+ 0x12, 0x2e,
+ 0x01, 0x86, 0x3f,
];
/// `std::sync::atomic` types via the `compare_exchange` method by passing
/// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
/// as both the `success` and `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+ /// [`AtomicBool::compare_exchange`][compare_exchange].
+ ///
+ /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
pub fn atomic_cxchg<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// `std::sync::atomic` types via the `compare_exchange` method by passing
/// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
/// as both the `success` and `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+ /// [`AtomicBool::compare_exchange`][compare_exchange].
+ ///
+ /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
pub fn atomic_cxchg_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+ /// [`AtomicBool::compare_exchange`][compare_exchange].
+ ///
+ /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+ /// [`AtomicBool::compare_exchange`][compare_exchange].
+ ///
+ /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
pub fn atomic_cxchg_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// `std::sync::atomic` types via the `compare_exchange` method by passing
/// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
/// as both the `success` and `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+ /// [`AtomicBool::compare_exchange`][compare_exchange].
+ ///
+ /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
pub fn atomic_cxchg_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+ /// [`AtomicBool::compare_exchange`][compare_exchange].
+ ///
+ /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
pub fn atomic_cxchg_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+ /// [`AtomicBool::compare_exchange`][compare_exchange].
+ ///
+ /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
pub fn atomic_cxchg_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+ /// [`AtomicBool::compare_exchange`][compare_exchange].
+ ///
+ /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
pub fn atomic_cxchg_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+ /// [`AtomicBool::compare_exchange`][compare_exchange].
+ ///
+ /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
pub fn atomic_cxchg_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
/// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
/// as both the `success` and `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange_weak`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+ /// [`AtomicBool::compare_exchange_weak`][cew].
+ ///
+ /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
pub fn atomic_cxchgweak<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
/// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
/// as both the `success` and `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange_weak`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+ /// [`AtomicBool::compare_exchange_weak`][cew].
+ ///
+ /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
pub fn atomic_cxchgweak_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange_weak`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+ /// [`AtomicBool::compare_exchange_weak`][cew].
+ ///
+ /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
pub fn atomic_cxchgweak_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange_weak`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+ /// [`AtomicBool::compare_exchange_weak`][cew].
+ ///
+ /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
pub fn atomic_cxchgweak_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
/// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
/// as both the `success` and `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange_weak`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+ /// [`AtomicBool::compare_exchange_weak`][cew].
+ ///
+ /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
pub fn atomic_cxchgweak_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange_weak`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+ /// [`AtomicBool::compare_exchange_weak`][cew].
+ ///
+ /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
pub fn atomic_cxchgweak_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange_weak`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+ /// [`AtomicBool::compare_exchange_weak`][cew].
+ ///
+ /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
pub fn atomic_cxchgweak_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange_weak`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+ /// [`AtomicBool::compare_exchange_weak`][cew].
+ ///
+ /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
pub fn atomic_cxchgweak_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Stores a value if the current value is the same as the `old` value.
/// The stabilized version of this intrinsic is available on the
/// as the `success` and
/// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
/// as the `failure` parameters. For example,
- /// [`AtomicBool::compare_exchange_weak`]
- /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+ /// [`AtomicBool::compare_exchange_weak`][cew].
+ ///
+ /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
pub fn atomic_cxchgweak_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
/// Loads the current value of the pointer.
#[cfg(not(stage0))]
pub fn unchecked_shr<T>(x: T, y: T) -> T;
- /// Returns (a + b) mod 2^N, where N is the width of T in bits.
+ /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `wrapping_add` method. For example,
/// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
pub fn overflowing_add<T>(a: T, b: T) -> T;
- /// Returns (a - b) mod 2^N, where N is the width of T in bits.
+ /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `wrapping_sub` method. For example,
/// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
pub fn overflowing_sub<T>(a: T, b: T) -> T;
- /// Returns (a * b) mod 2^N, where N is the width of T in bits.
+ /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `wrapping_mul` method. For example,
/// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
fn next(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next_back() }
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+
+ fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
+ where P: FnMut(&Self::Item) -> bool
+ {
+ self.iter.rfind(predicate)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator {
#[inline]
fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() }
+
+ fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
+ where P: FnMut(&Self::Item) -> bool
+ {
+ self.iter.find(predicate)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
Self: Sized,
P: FnMut(&Self::Item) -> bool
{
- for x in self.by_ref().rev() {
+ while let Some(x) = self.next_back() {
if predicate(&x) { return Some(x) }
}
None
//! inputs, but we don't do so to avoid the code bloat. Each bignum is still
//! tracked for the actual usages, so it normally doesn't matter.
-// This module is only for dec2flt and flt2dec, and only public because of libcoretest.
+// This module is only for dec2flt and flt2dec, and only public because of coretests.
// It is not intended to ever be stabilized.
#![doc(hidden)]
#![unstable(feature = "core_private_bignum",
//! Bit fiddling on positive IEEE 754 floats. Negative numbers aren't and needn't be handled.
//! Normal floating point numbers have a canonical representation as (frac, exp) such that the
-//! value is 2^exp * (1 + sum(frac[N-i] / 2^i)) where N is the number of bits. Subnormals are
-//! slightly different and weird, but the same principle applies.
+//! value is 2<sup>exp</sup> * (1 + sum(frac[N-i] / 2<sup>i</sup>)) where N is the number of bits.
+//! Subnormals are slightly different and weird, but the same principle applies.
//!
-//! Here, however, we represent them as (sig, k) with f positive, such that the value is f * 2^e.
-//! Besides making the "hidden bit" explicit, this changes the exponent by the so-called
-//! mantissa shift.
+//! Here, however, we represent them as (sig, k) with f positive, such that the value is f *
+//! 2<sup>e</sup>. Besides making the "hidden bit" explicit, this changes the exponent by the
+//! so-called mantissa shift.
//!
//! Put another way, normally floats are written as (1) but here they are written as (2):
//!
/// represented, the other code in this module makes sure to never let that happen.
fn from_int(x: u64) -> Self;
- /// Get the value 10^e from a pre-computed table. Panics for e >= ceil_log5_of_max_sig().
+ /// Get the value 10<sup>e</sup> from a pre-computed table. Panics for e >=
+ /// ceil_log5_of_max_sig().
fn short_fast_pow10(e: usize) -> Self;
// FIXME Everything that follows should be associated constants, but taking the value of an
//! Extended precision "soft float", for internal use only.
-// This module is only for dec2flt and flt2dec, and only public because of libcoretest.
+// This module is only for dec2flt and flt2dec, and only public because of coretests.
// It is not intended to ever be stabilized.
#![doc(hidden)]
#![unstable(feature = "core_private_diy_float",
string from resulting `Part`s itself.
All algorithms and formatting functions are accompanied by extensive tests
-in `coretest::num::flt2dec` module. It also shows how to use individual
+in `coretests::num::flt2dec` module. It also shows how to use individual
functions.
*/
mod wrapping;
-// All these modules are technically private and only exposed for libcoretest:
+// All these modules are technically private and only exposed for coretests:
pub mod flt2dec;
pub mod dec2flt;
pub mod bignum;
impl<A> FusedIterator for Item<A> {}
unsafe impl<A> TrustedLen for Item<A> {}
-/// An iterator over a reference of the contained item in an [`Option`].
+/// An iterator over a reference to the [`Some`] variant of an [`Option`].
+///
+/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.
+///
+/// This `struct` is created by the [`Option::iter`] function.
///
/// [`Option`]: enum.Option.html
+/// [`Some`]: enum.Option.html#variant.Some
+/// [`Option::iter`]: enum.Option.html#method.iter
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Iter<'a, A: 'a> { inner: Item<&'a A> }
}
}
-/// An iterator over a mutable reference of the contained item in an [`Option`].
+/// An iterator over a mutable reference to the [`Some`] variant of an [`Option`].
+///
+/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.
+///
+/// This `struct` is created by the [`Option::iter_mut`] function.
///
/// [`Option`]: enum.Option.html
+/// [`Some`]: enum.Option.html#variant.Some
+/// [`Option::iter_mut`]: enum.Option.html#method.iter_mut
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct IterMut<'a, A: 'a> { inner: Item<&'a mut A> }
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {}
-/// An iterator over the item contained inside an [`Option`].
+/// An iterator over the value in [`Some`] variant of an [`Option`].
+///
+/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.
+///
+/// This `struct` is created by the [`Option::into_iter`] function.
///
/// [`Option`]: enum.Option.html
+/// [`Some`]: enum.Option.html#variant.Some
+/// [`Option::into_iter`]: enum.Option.html#method.into_iter
#[derive(Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<A> { inner: Item<A> }
intrinsics::arith_offset(self, count)
}
}
+
+ /// Calculates the distance between two pointers. The returned value is in
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+ ///
+ /// If the address different between the two pointers ia not a multiple of
+ /// `mem::size_of::<T>()` then the result of the division is rounded towards
+ /// zero.
+ ///
+ /// This function returns `None` if `T` is a zero-sized typed.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(offset_to)]
+ ///
+ /// fn main() {
+ /// let a = [0; 5];
+ /// let ptr1: *const i32 = &a[1];
+ /// let ptr2: *const i32 = &a[3];
+ /// assert_eq!(ptr1.offset_to(ptr2), Some(2));
+ /// assert_eq!(ptr2.offset_to(ptr1), Some(-2));
+ /// assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
+ /// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
+ /// }
+ /// ```
+ #[unstable(feature = "offset_to", issue = "41079")]
+ #[inline]
+ pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
+ let size = mem::size_of::<T>();
+ if size == 0 {
+ None
+ } else {
+ let diff = (other as isize).wrapping_sub(self as isize);
+ Some(diff / size as isize)
+ }
+ }
}
#[lang = "mut_ptr"]
Some(&mut *self)
}
}
+
+ /// Calculates the distance between two pointers. The returned value is in
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+ ///
+ /// If the address different between the two pointers ia not a multiple of
+ /// `mem::size_of::<T>()` then the result of the division is rounded towards
+ /// zero.
+ ///
+ /// This function returns `None` if `T` is a zero-sized typed.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(offset_to)]
+ ///
+ /// fn main() {
+ /// let mut a = [0; 5];
+ /// let ptr1: *mut i32 = &mut a[1];
+ /// let ptr2: *mut i32 = &mut a[3];
+ /// assert_eq!(ptr1.offset_to(ptr2), Some(2));
+ /// assert_eq!(ptr2.offset_to(ptr1), Some(-2));
+ /// assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
+ /// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
+ /// }
+ /// ```
+ #[unstable(feature = "offset_to", issue = "41079")]
+ #[inline]
+ pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
+ let size = mem::size_of::<T>();
+ if size == 0 {
+ None
+ } else {
+ let diff = (other as isize).wrapping_sub(self as isize);
+ Some(diff / size as isize)
+ }
+ }
}
// Equality for pointers
fn split<P>(&self, pred: P) -> Split<Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
+ #[unstable(feature = "slice_rsplit", issue = "41020")]
+ fn rsplit<P>(&self, pred: P) -> RSplit<Self::Item, P>
+ where P: FnMut(&Self::Item) -> bool;
+
#[stable(feature = "core", since = "1.6.0")]
fn splitn<P>(&self, n: usize, pred: P) -> SplitN<Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
fn split_mut<P>(&mut self, pred: P) -> SplitMut<Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
+ #[unstable(feature = "slice_rsplit", issue = "41020")]
+ fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<Self::Item, P>
+ where P: FnMut(&Self::Item) -> bool;
+
#[stable(feature = "core", since = "1.6.0")]
fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
}
}
+ #[inline]
+ fn rsplit<P>(&self, pred: P) -> RSplit<T, P>
+ where P: FnMut(&T) -> bool
+ {
+ RSplit { inner: self.split(pred) }
+ }
+
#[inline]
fn splitn<P>(&self, n: usize, pred: P) -> SplitN<T, P>
where P: FnMut(&T) -> bool
SplitN {
inner: GenericSplitN {
iter: self.split(pred),
- count: n,
- invert: false
+ count: n
}
}
}
{
RSplitN {
inner: GenericSplitN {
- iter: self.split(pred),
- count: n,
- invert: true
+ iter: self.rsplit(pred),
+ count: n
}
}
}
SplitMut { v: self, pred: pred, finished: false }
}
+ #[inline]
+ fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<T, P>
+ where P: FnMut(&T) -> bool
+ {
+ RSplitMut { inner: self.split_mut(pred) }
+ }
+
#[inline]
fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<T, P>
where P: FnMut(&T) -> bool
SplitNMut {
inner: GenericSplitN {
iter: self.split_mut(pred),
- count: n,
- invert: false
+ count: n
}
}
}
{
RSplitNMut {
inner: GenericSplitN {
- iter: self.split_mut(pred),
- count: n,
- invert: true
+ iter: self.rsplit_mut(pred),
+ count: n
}
}
}
// Return the arithmetic difference if `T` is zero size.
#[inline(always)]
fn ptrdistance<T>(start: *const T, end: *const T) -> usize {
- let diff = (end as usize).wrapping_sub(start as usize);
- let size = mem::size_of::<T>();
- diff / (if size == 0 { 1 } else { size })
+ match start.offset_to(end) {
+ Some(x) => x as usize,
+ None => (end as usize).wrapping_sub(start as usize),
+ }
}
// Extension methods for raw pointers, used by the iterators
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
+/// An iterator over subslices separated by elements that match a predicate
+/// function, starting from the end of the slice.
+///
+/// This struct is created by the [`rsplit`] method on [slices].
+///
+/// [`rsplit`]: ../../std/primitive.slice.html#method.rsplit
+/// [slices]: ../../std/primitive.slice.html
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[derive(Clone)] // Is this correct, or does it incorrectly require `T: Clone`?
+pub struct RSplit<'a, T:'a, P> where P: FnMut(&T) -> bool {
+ inner: Split<'a, T, P>
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("RSplit")
+ .field("v", &self.inner.v)
+ .field("finished", &self.inner.finished)
+ .finish()
+ }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> Iterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
+ type Item = &'a [T];
+
+ #[inline]
+ fn next(&mut self) -> Option<&'a [T]> {
+ self.inner.next_back()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> DoubleEndedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a [T]> {
+ self.inner.next()
+ }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> SplitIter for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
+ #[inline]
+ fn finish(&mut self) -> Option<&'a [T]> {
+ self.inner.finish()
+ }
+}
+
+//#[unstable(feature = "fused", issue = "35602")]
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> FusedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {}
+
+/// An iterator over the subslices of the vector which are separated
+/// by elements that match `pred`, starting from the end of the slice.
+///
+/// This struct is created by the [`rsplit_mut`] method on [slices].
+///
+/// [`rsplit_mut`]: ../../std/primitive.slice.html#method.rsplit_mut
+/// [slices]: ../../std/primitive.slice.html
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+pub struct RSplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
+ inner: SplitMut<'a, T, P>
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("RSplitMut")
+ .field("v", &self.inner.v)
+ .field("finished", &self.inner.finished)
+ .finish()
+ }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> SplitIter for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
+ #[inline]
+ fn finish(&mut self) -> Option<&'a mut [T]> {
+ self.inner.finish()
+ }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> Iterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
+ type Item = &'a mut [T];
+
+ #[inline]
+ fn next(&mut self) -> Option<&'a mut [T]> {
+ self.inner.next_back()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> DoubleEndedIterator for RSplitMut<'a, T, P> where
+ P: FnMut(&T) -> bool,
+{
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a mut [T]> {
+ self.inner.next()
+ }
+}
+
+//#[unstable(feature = "fused", issue = "35602")]
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> FusedIterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
+
/// An private iterator over subslices separated by elements that
/// match a predicate function, splitting at most a fixed number of
/// times.
struct GenericSplitN<I> {
iter: I,
count: usize,
- invert: bool
}
impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
match self.count {
0 => None,
1 => { self.count -= 1; self.iter.finish() }
- _ => {
- self.count -= 1;
- if self.invert {self.iter.next_back()} else {self.iter.next()}
- }
+ _ => { self.count -= 1; self.iter.next() }
}
}
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
- inner: GenericSplitN<Split<'a, T, P>>
+ inner: GenericSplitN<RSplit<'a, T, P>>
}
#[stable(feature = "core_impl_debug", since = "1.9.0")]
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
- inner: GenericSplitN<SplitMut<'a, T, P>>
+ inner: GenericSplitN<RSplitMut<'a, T, P>>
}
#[stable(feature = "core_impl_debug", since = "1.9.0")]
Section: Creating a string
*/
-/// Errors which can occur when attempting to interpret a sequence of `u8`
+/// Errors which can occur when attempting to interpret a sequence of [`u8`]
/// as a string.
///
-/// As such, the `from_utf8` family of functions and methods for both `String`s
-/// and `&str`s make use of this error, for example.
+/// [`u8`]: ../../std/primitive.u8.html
+///
+/// As such, the `from_utf8` family of functions and methods for both [`String`]s
+/// and [`&str`]s make use of this error, for example.
+///
+/// [`String`]: ../../std/string/struct.String.html#method.from_utf8
+/// [`&str`]: ../../std/str/fn.from_utf8.html
#[derive(Copy, Eq, PartialEq, Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Utf8Error {
/// Converts a slice of bytes to a string slice.
///
-/// A string slice (`&str`) is made of bytes (`u8`), and a byte slice (`&[u8]`)
-/// is made of bytes, so this function converts between the two. Not all byte
-/// slices are valid string slices, however: `&str` requires that it is valid
-/// UTF-8. `from_utf8()` checks to ensure that the bytes are valid UTF-8, and
-/// then does the conversion.
+/// A string slice ([`&str`]) is made of bytes ([`u8`]), and a byte slice
+/// ([`&[u8]`][byteslice]) is made of bytes, so this function converts between
+/// the two. Not all byte slices are valid string slices, however: [`&str`] requires
+/// that it is valid UTF-8. `from_utf8()` checks to ensure that the bytes are valid
+/// UTF-8, and then does the conversion.
+///
+/// [`&str`]: ../../std/primitive.str.html
+/// [`u8`]: ../../std/primitive.u8.html
+/// [byteslice]: ../../std/primitive.slice.html
///
/// If you are sure that the byte slice is valid UTF-8, and you don't want to
/// incur the overhead of the validity check, there is an unsafe version of
///
/// [string]: ../../std/string/struct.String.html#method.from_utf8
///
-/// Because you can stack-allocate a `[u8; N]`, and you can take a `&[u8]` of
-/// it, this function is one way to have a stack-allocated string. There is
-/// an example of this in the examples section below.
+/// Because you can stack-allocate a `[u8; N]`, and you can take a
+/// [`&[u8]`][byteslice] of it, this function is one way to have a
+/// stack-allocated string. There is an example of this in the
+/// examples section below.
+///
+/// [byteslice]: ../../std/primitive.slice.html
///
/// # Errors
///
}
}
- /// Stores a value into the bool, returning the old value.
+ /// Stores a value into the bool, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation.
}
}
- /// Stores a value into the pointer, returning the old value.
+ /// Stores a value into the pointer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation.
unsafe { atomic_store(self.v.get(), val, order); }
}
- /// Stores a value into the atomic integer, returning the old value.
+ /// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering of this
/// operation.
}
}
- /// Add to the current value, returning the previous value.
+ /// Adds to the current value, returning the previous value.
+ ///
+ /// This operation wraps around on overflow.
///
/// # Examples
///
unsafe { atomic_add(self.v.get(), val, order) }
}
- /// Subtract from the current value, returning the previous value.
+ /// Subtracts from the current value, returning the previous value.
+ ///
+ /// This operation wraps around on overflow.
///
/// # Examples
///
unsafe { atomic_sub(self.v.get(), val, order) }
}
- /// Bitwise and with the current value, returning the previous value.
+ /// Bitwise "and" with the current value.
+ ///
+ /// Performs a bitwise "and" operation on the current value and the argument `val`, and
+ /// sets the new value to the result.
+ ///
+ /// Returns the previous value.
///
/// # Examples
///
unsafe { atomic_and(self.v.get(), val, order) }
}
- /// Bitwise or with the current value, returning the previous value.
+ /// Bitwise "or" with the current value.
+ ///
+ /// Performs a bitwise "or" operation on the current value and the argument `val`, and
+ /// sets the new value to the result.
+ ///
+ /// Returns the previous value.
///
/// # Examples
///
unsafe { atomic_or(self.v.get(), val, order) }
}
- /// Bitwise xor with the current value, returning the previous value.
+ /// Bitwise "xor" with the current value.
+ ///
+ /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
+ /// sets the new value to the result.
+ ///
+ /// Returns the previous value.
///
/// # Examples
///
}
}
-/// Returns the old value (like __sync_fetch_and_add).
+/// Returns the previous value (like __sync_fetch_and_add).
#[inline]
unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
}
}
-/// Returns the old value (like __sync_fetch_and_sub).
+/// Returns the previous value (like __sync_fetch_and_sub).
#[inline]
unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
--- /dev/null
+// Copyright 2014 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.
+
+use core::any::*;
+
+#[derive(PartialEq, Debug)]
+struct Test;
+
+static TEST: &'static str = "Test";
+
+#[test]
+fn any_referenced() {
+ let (a, b, c) = (&5 as &Any, &TEST as &Any, &Test as &Any);
+
+ assert!(a.is::<i32>());
+ assert!(!b.is::<i32>());
+ assert!(!c.is::<i32>());
+
+ assert!(!a.is::<&'static str>());
+ assert!(b.is::<&'static str>());
+ assert!(!c.is::<&'static str>());
+
+ assert!(!a.is::<Test>());
+ assert!(!b.is::<Test>());
+ assert!(c.is::<Test>());
+}
+
+#[test]
+fn any_owning() {
+ let (a, b, c) = (box 5_usize as Box<Any>, box TEST as Box<Any>, box Test as Box<Any>);
+
+ assert!(a.is::<usize>());
+ assert!(!b.is::<usize>());
+ assert!(!c.is::<usize>());
+
+ assert!(!a.is::<&'static str>());
+ assert!(b.is::<&'static str>());
+ assert!(!c.is::<&'static str>());
+
+ assert!(!a.is::<Test>());
+ assert!(!b.is::<Test>());
+ assert!(c.is::<Test>());
+}
+
+#[test]
+fn any_downcast_ref() {
+ let a = &5_usize as &Any;
+
+ match a.downcast_ref::<usize>() {
+ Some(&5) => {}
+ x => panic!("Unexpected value {:?}", x)
+ }
+
+ match a.downcast_ref::<Test>() {
+ None => {}
+ x => panic!("Unexpected value {:?}", x)
+ }
+}
+
+#[test]
+fn any_downcast_mut() {
+ let mut a = 5_usize;
+ let mut b: Box<_> = box 7_usize;
+
+ let a_r = &mut a as &mut Any;
+ let tmp: &mut usize = &mut *b;
+ let b_r = tmp as &mut Any;
+
+ match a_r.downcast_mut::<usize>() {
+ Some(x) => {
+ assert_eq!(*x, 5);
+ *x = 612;
+ }
+ x => panic!("Unexpected value {:?}", x)
+ }
+
+ match b_r.downcast_mut::<usize>() {
+ Some(x) => {
+ assert_eq!(*x, 7);
+ *x = 413;
+ }
+ x => panic!("Unexpected value {:?}", x)
+ }
+
+ match a_r.downcast_mut::<Test>() {
+ None => (),
+ x => panic!("Unexpected value {:?}", x)
+ }
+
+ match b_r.downcast_mut::<Test>() {
+ None => (),
+ x => panic!("Unexpected value {:?}", x)
+ }
+
+ match a_r.downcast_mut::<usize>() {
+ Some(&mut 612) => {}
+ x => panic!("Unexpected value {:?}", x)
+ }
+
+ match b_r.downcast_mut::<usize>() {
+ Some(&mut 413) => {}
+ x => panic!("Unexpected value {:?}", x)
+ }
+}
+
+#[test]
+fn any_fixed_vec() {
+ let test = [0_usize; 8];
+ let test = &test as &Any;
+ assert!(test.is::<[usize; 8]>());
+ assert!(!test.is::<[usize; 10]>());
+}
+
+#[test]
+fn any_unsized() {
+ fn is_any<T: Any + ?Sized>() {}
+ is_any::<[i32]>();
+}
--- /dev/null
+// Copyright 2014 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.
+use core::array::FixedSizeArray;
+
+#[test]
+fn fixed_size_array() {
+ let mut array = [0; 64];
+ let mut zero_sized = [(); 64];
+ let mut empty_array = [0; 0];
+ let mut empty_zero_sized = [(); 0];
+
+ assert_eq!(FixedSizeArray::as_slice(&array).len(), 64);
+ assert_eq!(FixedSizeArray::as_slice(&zero_sized).len(), 64);
+ assert_eq!(FixedSizeArray::as_slice(&empty_array).len(), 0);
+ assert_eq!(FixedSizeArray::as_slice(&empty_zero_sized).len(), 0);
+
+ assert_eq!(FixedSizeArray::as_mut_slice(&mut array).len(), 64);
+ assert_eq!(FixedSizeArray::as_mut_slice(&mut zero_sized).len(), 64);
+ assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0);
+ assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0);
+}
--- /dev/null
+// Copyright 2014 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.
+
+use core::sync::atomic::*;
+use core::sync::atomic::Ordering::SeqCst;
+
+#[test]
+fn bool_() {
+ let a = AtomicBool::new(false);
+ assert_eq!(a.compare_and_swap(false, true, SeqCst), false);
+ assert_eq!(a.compare_and_swap(false, true, SeqCst), true);
+
+ a.store(false, SeqCst);
+ assert_eq!(a.compare_and_swap(false, true, SeqCst), false);
+}
+
+#[test]
+fn bool_and() {
+ let a = AtomicBool::new(true);
+ assert_eq!(a.fetch_and(false, SeqCst),true);
+ assert_eq!(a.load(SeqCst),false);
+}
+
+#[test]
+fn uint_and() {
+ let x = AtomicUsize::new(0xf731);
+ assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
+ assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
+}
+
+#[test]
+fn uint_or() {
+ let x = AtomicUsize::new(0xf731);
+ assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
+ assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
+}
+
+#[test]
+fn uint_xor() {
+ let x = AtomicUsize::new(0xf731);
+ assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
+ assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
+}
+
+#[test]
+fn int_and() {
+ let x = AtomicIsize::new(0xf731);
+ assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
+ assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
+}
+
+#[test]
+fn int_or() {
+ let x = AtomicIsize::new(0xf731);
+ assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
+ assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
+}
+
+#[test]
+fn int_xor() {
+ let x = AtomicIsize::new(0xf731);
+ assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
+ assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
+}
+
+static S_FALSE: AtomicBool = AtomicBool::new(false);
+static S_TRUE: AtomicBool = AtomicBool::new(true);
+static S_INT: AtomicIsize = AtomicIsize::new(0);
+static S_UINT: AtomicUsize = AtomicUsize::new(0);
+
+#[test]
+fn static_init() {
+ assert!(!S_FALSE.load(SeqCst));
+ assert!(S_TRUE.load(SeqCst));
+ assert!(S_INT.load(SeqCst) == 0);
+ assert!(S_UINT.load(SeqCst) == 0);
+}
--- /dev/null
+// Copyright 2014 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.
+
+use core::cell::*;
+use core::default::Default;
+use std::mem::drop;
+
+#[test]
+fn smoketest_cell() {
+ let x = Cell::new(10);
+ assert!(x == Cell::new(10));
+ assert!(x.get() == 10);
+ x.set(20);
+ assert!(x == Cell::new(20));
+ assert!(x.get() == 20);
+
+ let y = Cell::new((30, 40));
+ assert!(y == Cell::new((30, 40)));
+ assert!(y.get() == (30, 40));
+}
+
+#[test]
+fn cell_has_sensible_show() {
+ let x = Cell::new("foo bar");
+ assert!(format!("{:?}", x).contains(x.get()));
+
+ x.set("baz qux");
+ assert!(format!("{:?}", x).contains(x.get()));
+}
+
+#[test]
+fn ref_and_refmut_have_sensible_show() {
+ let refcell = RefCell::new("foo");
+
+ let refcell_refmut = refcell.borrow_mut();
+ assert!(format!("{:?}", refcell_refmut).contains("foo"));
+ drop(refcell_refmut);
+
+ let refcell_ref = refcell.borrow();
+ assert!(format!("{:?}", refcell_ref).contains("foo"));
+ drop(refcell_ref);
+}
+
+#[test]
+fn double_imm_borrow() {
+ let x = RefCell::new(0);
+ let _b1 = x.borrow();
+ x.borrow();
+}
+
+#[test]
+fn no_mut_then_imm_borrow() {
+ let x = RefCell::new(0);
+ let _b1 = x.borrow_mut();
+ assert!(x.try_borrow().is_err());
+}
+
+#[test]
+fn no_imm_then_borrow_mut() {
+ let x = RefCell::new(0);
+ let _b1 = x.borrow();
+ assert!(x.try_borrow_mut().is_err());
+}
+
+#[test]
+fn no_double_borrow_mut() {
+ let x = RefCell::new(0);
+ assert!(x.try_borrow().is_ok());
+ let _b1 = x.borrow_mut();
+ assert!(x.try_borrow().is_err());
+}
+
+#[test]
+fn imm_release_borrow_mut() {
+ let x = RefCell::new(0);
+ {
+ let _b1 = x.borrow();
+ }
+ x.borrow_mut();
+}
+
+#[test]
+fn mut_release_borrow_mut() {
+ let x = RefCell::new(0);
+ {
+ let _b1 = x.borrow_mut();
+ }
+ x.borrow();
+}
+
+#[test]
+fn double_borrow_single_release_no_borrow_mut() {
+ let x = RefCell::new(0);
+ let _b1 = x.borrow();
+ {
+ let _b2 = x.borrow();
+ }
+ assert!(x.try_borrow().is_ok());
+ assert!(x.try_borrow_mut().is_err());
+}
+
+#[test]
+#[should_panic]
+fn discard_doesnt_unborrow() {
+ let x = RefCell::new(0);
+ let _b = x.borrow();
+ let _ = _b;
+ let _b = x.borrow_mut();
+}
+
+#[test]
+fn ref_clone_updates_flag() {
+ let x = RefCell::new(0);
+ {
+ let b1 = x.borrow();
+ assert!(x.try_borrow().is_ok());
+ assert!(x.try_borrow_mut().is_err());
+ {
+ let _b2 = Ref::clone(&b1);
+ assert!(x.try_borrow().is_ok());
+ assert!(x.try_borrow_mut().is_err());
+ }
+ assert!(x.try_borrow().is_ok());
+ assert!(x.try_borrow_mut().is_err());
+ }
+ assert!(x.try_borrow().is_ok());
+ assert!(x.try_borrow_mut().is_ok());
+}
+
+#[test]
+fn ref_map_does_not_update_flag() {
+ let x = RefCell::new(Some(5));
+ {
+ let b1: Ref<Option<u32>> = x.borrow();
+ assert!(x.try_borrow().is_ok());
+ assert!(x.try_borrow_mut().is_err());
+ {
+ let b2: Ref<u32> = Ref::map(b1, |o| o.as_ref().unwrap());
+ assert_eq!(*b2, 5);
+ assert!(x.try_borrow().is_ok());
+ assert!(x.try_borrow_mut().is_err());
+ }
+ assert!(x.try_borrow().is_ok());
+ assert!(x.try_borrow_mut().is_ok());
+ }
+ assert!(x.try_borrow().is_ok());
+ assert!(x.try_borrow_mut().is_ok());
+}
+
+#[test]
+fn ref_map_accessor() {
+ struct X(RefCell<(u32, char)>);
+ impl X {
+ fn accessor(&self) -> Ref<u32> {
+ Ref::map(self.0.borrow(), |tuple| &tuple.0)
+ }
+ }
+ let x = X(RefCell::new((7, 'z')));
+ let d: Ref<u32> = x.accessor();
+ assert_eq!(*d, 7);
+}
+
+#[test]
+fn ref_mut_map_accessor() {
+ struct X(RefCell<(u32, char)>);
+ impl X {
+ fn accessor(&self) -> RefMut<u32> {
+ RefMut::map(self.0.borrow_mut(), |tuple| &mut tuple.0)
+ }
+ }
+ let x = X(RefCell::new((7, 'z')));
+ {
+ let mut d: RefMut<u32> = x.accessor();
+ assert_eq!(*d, 7);
+ *d += 1;
+ }
+ assert_eq!(*x.0.borrow(), (8, 'z'));
+}
+
+#[test]
+fn as_ptr() {
+ let c1: Cell<usize> = Cell::new(0);
+ c1.set(1);
+ assert_eq!(1, unsafe { *c1.as_ptr() });
+
+ let c2: Cell<usize> = Cell::new(0);
+ unsafe { *c2.as_ptr() = 1; }
+ assert_eq!(1, c2.get());
+
+ let r1: RefCell<usize> = RefCell::new(0);
+ *r1.borrow_mut() = 1;
+ assert_eq!(1, unsafe { *r1.as_ptr() });
+
+ let r2: RefCell<usize> = RefCell::new(0);
+ unsafe { *r2.as_ptr() = 1; }
+ assert_eq!(1, *r2.borrow());
+}
+
+#[test]
+fn cell_default() {
+ let cell: Cell<u32> = Default::default();
+ assert_eq!(0, cell.get());
+}
+
+#[test]
+fn cell_set() {
+ let cell = Cell::new(10);
+ cell.set(20);
+ assert_eq!(20, cell.get());
+
+ let cell = Cell::new("Hello".to_owned());
+ cell.set("World".to_owned());
+ assert_eq!("World".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn cell_replace() {
+ let cell = Cell::new(10);
+ assert_eq!(10, cell.replace(20));
+ assert_eq!(20, cell.get());
+
+ let cell = Cell::new("Hello".to_owned());
+ assert_eq!("Hello".to_owned(), cell.replace("World".to_owned()));
+ assert_eq!("World".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn cell_into_inner() {
+ let cell = Cell::new(10);
+ assert_eq!(10, cell.into_inner());
+
+ let cell = Cell::new("Hello world".to_owned());
+ assert_eq!("Hello world".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn refcell_default() {
+ let cell: RefCell<u64> = Default::default();
+ assert_eq!(0, *cell.borrow());
+}
+
+#[test]
+fn unsafe_cell_unsized() {
+ let cell: &UnsafeCell<[i32]> = &UnsafeCell::new([1, 2, 3]);
+ {
+ let val: &mut [i32] = unsafe { &mut *cell.get() };
+ val[0] = 4;
+ val[2] = 5;
+ }
+ let comp: &mut [i32] = &mut [4, 2, 5];
+ assert_eq!(unsafe { &mut *cell.get() }, comp);
+}
+
+#[test]
+fn refcell_unsized() {
+ let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
+ {
+ let b = &mut *cell.borrow_mut();
+ b[0] = 4;
+ b[2] = 5;
+ }
+ let comp: &mut [i32] = &mut [4, 2, 5];
+ assert_eq!(&*cell.borrow(), comp);
+}
+
+#[test]
+fn refcell_ref_coercion() {
+ let cell: RefCell<[i32; 3]> = RefCell::new([1, 2, 3]);
+ {
+ let mut cellref: RefMut<[i32; 3]> = cell.borrow_mut();
+ cellref[0] = 4;
+ let mut coerced: RefMut<[i32]> = cellref;
+ coerced[2] = 5;
+ }
+ {
+ let comp: &mut [i32] = &mut [4, 2, 5];
+ let cellref: Ref<[i32; 3]> = cell.borrow();
+ assert_eq!(&*cellref, comp);
+ let coerced: Ref<[i32]> = cellref;
+ assert_eq!(&*coerced, comp);
+ }
+}
--- /dev/null
+// Copyright 2014 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.
+
+use std::{char,str};
+use std::convert::TryFrom;
+
+#[test]
+fn test_convert() {
+ assert_eq!(u32::from('a'), 0x61);
+ assert_eq!(char::from(b'\0'), '\0');
+ assert_eq!(char::from(b'a'), 'a');
+ assert_eq!(char::from(b'\xFF'), '\u{FF}');
+ assert_eq!(char::try_from(0_u32), Ok('\0'));
+ assert_eq!(char::try_from(0x61_u32), Ok('a'));
+ assert_eq!(char::try_from(0xD7FF_u32), Ok('\u{D7FF}'));
+ assert!(char::try_from(0xD800_u32).is_err());
+ assert!(char::try_from(0xDFFF_u32).is_err());
+ assert_eq!(char::try_from(0xE000_u32), Ok('\u{E000}'));
+ assert_eq!(char::try_from(0x10FFFF_u32), Ok('\u{10FFFF}'));
+ assert!(char::try_from(0x110000_u32).is_err());
+ assert!(char::try_from(0xFFFF_FFFF_u32).is_err());
+}
+
+#[test]
+fn test_is_lowercase() {
+ assert!('a'.is_lowercase());
+ assert!('ö'.is_lowercase());
+ assert!('ß'.is_lowercase());
+ assert!(!'Ü'.is_lowercase());
+ assert!(!'P'.is_lowercase());
+}
+
+#[test]
+fn test_is_uppercase() {
+ assert!(!'h'.is_uppercase());
+ assert!(!'ä'.is_uppercase());
+ assert!(!'ß'.is_uppercase());
+ assert!('Ö'.is_uppercase());
+ assert!('T'.is_uppercase());
+}
+
+#[test]
+fn test_is_whitespace() {
+ assert!(' '.is_whitespace());
+ assert!('\u{2007}'.is_whitespace());
+ assert!('\t'.is_whitespace());
+ assert!('\n'.is_whitespace());
+ assert!(!'a'.is_whitespace());
+ assert!(!'_'.is_whitespace());
+ assert!(!'\u{0}'.is_whitespace());
+}
+
+#[test]
+fn test_to_digit() {
+ assert_eq!('0'.to_digit(10), Some(0));
+ assert_eq!('1'.to_digit(2), Some(1));
+ assert_eq!('2'.to_digit(3), Some(2));
+ assert_eq!('9'.to_digit(10), Some(9));
+ assert_eq!('a'.to_digit(16), Some(10));
+ assert_eq!('A'.to_digit(16), Some(10));
+ assert_eq!('b'.to_digit(16), Some(11));
+ assert_eq!('B'.to_digit(16), Some(11));
+ assert_eq!('z'.to_digit(36), Some(35));
+ assert_eq!('Z'.to_digit(36), Some(35));
+ assert_eq!(' '.to_digit(10), None);
+ assert_eq!('$'.to_digit(36), None);
+}
+
+#[test]
+fn test_to_lowercase() {
+ fn lower(c: char) -> String {
+ let iter: String = c.to_lowercase().collect();
+ let disp: String = c.to_lowercase().to_string();
+ assert_eq!(iter, disp);
+ iter
+ }
+ assert_eq!(lower('A'), "a");
+ assert_eq!(lower('Ö'), "ö");
+ assert_eq!(lower('ß'), "ß");
+ assert_eq!(lower('Ü'), "ü");
+ assert_eq!(lower('💩'), "💩");
+ assert_eq!(lower('Σ'), "σ");
+ assert_eq!(lower('Τ'), "τ");
+ assert_eq!(lower('Ι'), "ι");
+ assert_eq!(lower('Γ'), "γ");
+ assert_eq!(lower('Μ'), "μ");
+ assert_eq!(lower('Α'), "α");
+ assert_eq!(lower('Σ'), "σ");
+ assert_eq!(lower('Dž'), "dž");
+ assert_eq!(lower('fi'), "fi");
+ assert_eq!(lower('İ'), "i\u{307}");
+}
+
+#[test]
+fn test_to_uppercase() {
+ fn upper(c: char) -> String {
+ let iter: String = c.to_uppercase().collect();
+ let disp: String = c.to_uppercase().to_string();
+ assert_eq!(iter, disp);
+ iter
+ }
+ assert_eq!(upper('a'), "A");
+ assert_eq!(upper('ö'), "Ö");
+ assert_eq!(upper('ß'), "SS"); // not ẞ: Latin capital letter sharp s
+ assert_eq!(upper('ü'), "Ü");
+ assert_eq!(upper('💩'), "💩");
+
+ assert_eq!(upper('σ'), "Σ");
+ assert_eq!(upper('τ'), "Τ");
+ assert_eq!(upper('ι'), "Ι");
+ assert_eq!(upper('γ'), "Γ");
+ assert_eq!(upper('μ'), "Μ");
+ assert_eq!(upper('α'), "Α");
+ assert_eq!(upper('ς'), "Σ");
+ assert_eq!(upper('Dž'), "DŽ");
+ assert_eq!(upper('fi'), "FI");
+ assert_eq!(upper('ᾀ'), "ἈΙ");
+}
+
+#[test]
+fn test_is_control() {
+ assert!('\u{0}'.is_control());
+ assert!('\u{3}'.is_control());
+ assert!('\u{6}'.is_control());
+ assert!('\u{9}'.is_control());
+ assert!('\u{7f}'.is_control());
+ assert!('\u{92}'.is_control());
+ assert!(!'\u{20}'.is_control());
+ assert!(!'\u{55}'.is_control());
+ assert!(!'\u{68}'.is_control());
+}
+
+#[test]
+fn test_is_digit() {
+ assert!('2'.is_numeric());
+ assert!('7'.is_numeric());
+ assert!(!'c'.is_numeric());
+ assert!(!'i'.is_numeric());
+ assert!(!'z'.is_numeric());
+ assert!(!'Q'.is_numeric());
+}
+
+#[test]
+fn test_escape_debug() {
+ fn string(c: char) -> String {
+ let iter: String = c.escape_debug().collect();
+ let disp: String = c.escape_debug().to_string();
+ assert_eq!(iter, disp);
+ iter
+ }
+ assert_eq!(string('\n'), "\\n");
+ assert_eq!(string('\r'), "\\r");
+ assert_eq!(string('\''), "\\'");
+ assert_eq!(string('"'), "\\\"");
+ assert_eq!(string(' '), " ");
+ assert_eq!(string('a'), "a");
+ assert_eq!(string('~'), "~");
+ assert_eq!(string('é'), "é");
+ assert_eq!(string('文'), "文");
+ assert_eq!(string('\x00'), "\\u{0}");
+ assert_eq!(string('\x1f'), "\\u{1f}");
+ assert_eq!(string('\x7f'), "\\u{7f}");
+ assert_eq!(string('\u{80}'), "\\u{80}");
+ assert_eq!(string('\u{ff}'), "\u{ff}");
+ assert_eq!(string('\u{11b}'), "\u{11b}");
+ assert_eq!(string('\u{1d4b6}'), "\u{1d4b6}");
+ assert_eq!(string('\u{200b}'),"\\u{200b}"); // zero width space
+ assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1
+ assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2
+}
+
+#[test]
+fn test_escape_default() {
+ fn string(c: char) -> String {
+ let iter: String = c.escape_default().collect();
+ let disp: String = c.escape_default().to_string();
+ assert_eq!(iter, disp);
+ iter
+ }
+ assert_eq!(string('\n'), "\\n");
+ assert_eq!(string('\r'), "\\r");
+ assert_eq!(string('\''), "\\'");
+ assert_eq!(string('"'), "\\\"");
+ assert_eq!(string(' '), " ");
+ assert_eq!(string('a'), "a");
+ assert_eq!(string('~'), "~");
+ assert_eq!(string('é'), "\\u{e9}");
+ assert_eq!(string('\x00'), "\\u{0}");
+ assert_eq!(string('\x1f'), "\\u{1f}");
+ assert_eq!(string('\x7f'), "\\u{7f}");
+ assert_eq!(string('\u{80}'), "\\u{80}");
+ assert_eq!(string('\u{ff}'), "\\u{ff}");
+ assert_eq!(string('\u{11b}'), "\\u{11b}");
+ assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}");
+ assert_eq!(string('\u{200b}'), "\\u{200b}"); // zero width space
+ assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1
+ assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2
+}
+
+#[test]
+fn test_escape_unicode() {
+ fn string(c: char) -> String {
+ let iter: String = c.escape_unicode().collect();
+ let disp: String = c.escape_unicode().to_string();
+ assert_eq!(iter, disp);
+ iter
+ }
+
+ assert_eq!(string('\x00'), "\\u{0}");
+ assert_eq!(string('\n'), "\\u{a}");
+ assert_eq!(string(' '), "\\u{20}");
+ assert_eq!(string('a'), "\\u{61}");
+ assert_eq!(string('\u{11b}'), "\\u{11b}");
+ assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}");
+}
+
+#[test]
+fn test_encode_utf8() {
+ fn check(input: char, expect: &[u8]) {
+ let mut buf = [0; 4];
+ let ptr = buf.as_ptr();
+ let s = input.encode_utf8(&mut buf);
+ assert_eq!(s.as_ptr() as usize, ptr as usize);
+ assert!(str::from_utf8(s.as_bytes()).is_ok());
+ assert_eq!(s.as_bytes(), expect);
+ }
+
+ check('x', &[0x78]);
+ check('\u{e9}', &[0xc3, 0xa9]);
+ check('\u{a66e}', &[0xea, 0x99, 0xae]);
+ check('\u{1f4a9}', &[0xf0, 0x9f, 0x92, 0xa9]);
+}
+
+#[test]
+fn test_encode_utf16() {
+ fn check(input: char, expect: &[u16]) {
+ let mut buf = [0; 2];
+ let ptr = buf.as_mut_ptr();
+ let b = input.encode_utf16(&mut buf);
+ assert_eq!(b.as_mut_ptr() as usize, ptr as usize);
+ assert_eq!(b, expect);
+ }
+
+ check('x', &[0x0078]);
+ check('\u{e9}', &[0x00e9]);
+ check('\u{a66e}', &[0xa66e]);
+ check('\u{1f4a9}', &[0xd83d, 0xdca9]);
+}
+
+#[test]
+fn test_len_utf16() {
+ assert!('x'.len_utf16() == 1);
+ assert!('\u{e9}'.len_utf16() == 1);
+ assert!('\u{a66e}'.len_utf16() == 1);
+ assert!('\u{1f4a9}'.len_utf16() == 2);
+}
+
+#[test]
+fn test_decode_utf16() {
+ fn check(s: &[u16], expected: &[Result<char, u16>]) {
+ let v = char::decode_utf16(s.iter().cloned())
+ .map(|r| r.map_err(|e| e.unpaired_surrogate()))
+ .collect::<Vec<_>>();
+ assert_eq!(v, expected);
+ }
+ check(&[0xD800, 0x41, 0x42], &[Err(0xD800), Ok('A'), Ok('B')]);
+ check(&[0xD800, 0], &[Err(0xD800), Ok('\0')]);
+}
+
+#[test]
+fn ed_iterator_specializations() {
+ // Check counting
+ assert_eq!('\n'.escape_default().count(), 2);
+ assert_eq!('c'.escape_default().count(), 1);
+ assert_eq!(' '.escape_default().count(), 1);
+ assert_eq!('\\'.escape_default().count(), 2);
+ assert_eq!('\''.escape_default().count(), 2);
+
+ // Check nth
+
+ // Check that OoB is handled correctly
+ assert_eq!('\n'.escape_default().nth(2), None);
+ assert_eq!('c'.escape_default().nth(1), None);
+ assert_eq!(' '.escape_default().nth(1), None);
+ assert_eq!('\\'.escape_default().nth(2), None);
+ assert_eq!('\''.escape_default().nth(2), None);
+
+ // Check the first char
+ assert_eq!('\n'.escape_default().nth(0), Some('\\'));
+ assert_eq!('c'.escape_default().nth(0), Some('c'));
+ assert_eq!(' '.escape_default().nth(0), Some(' '));
+ assert_eq!('\\'.escape_default().nth(0), Some('\\'));
+ assert_eq!('\''.escape_default().nth(0), Some('\\'));
+
+ // Check the second char
+ assert_eq!('\n'.escape_default().nth(1), Some('n'));
+ assert_eq!('\\'.escape_default().nth(1), Some('\\'));
+ assert_eq!('\''.escape_default().nth(1), Some('\''));
+
+ // Check the last char
+ assert_eq!('\n'.escape_default().last(), Some('n'));
+ assert_eq!('c'.escape_default().last(), Some('c'));
+ assert_eq!(' '.escape_default().last(), Some(' '));
+ assert_eq!('\\'.escape_default().last(), Some('\\'));
+ assert_eq!('\''.escape_default().last(), Some('\''));
+}
+
+#[test]
+fn eu_iterator_specializations() {
+ fn check(c: char) {
+ let len = c.escape_unicode().count();
+
+ // Check OoB
+ assert_eq!(c.escape_unicode().nth(len), None);
+
+ // For all possible in-bound offsets
+ let mut iter = c.escape_unicode();
+ for offset in 0..len {
+ // Check last
+ assert_eq!(iter.clone().last(), Some('}'));
+
+ // Check len
+ assert_eq!(iter.len(), len - offset);
+
+ // Check size_hint (= len in ExactSizeIterator)
+ assert_eq!(iter.size_hint(), (iter.len(), Some(iter.len())));
+
+ // Check counting
+ assert_eq!(iter.clone().count(), len - offset);
+
+ // Check nth
+ assert_eq!(c.escape_unicode().nth(offset), iter.next());
+ }
+
+ // Check post-last
+ assert_eq!(iter.clone().last(), None);
+ assert_eq!(iter.clone().count(), 0);
+ }
+
+ check('\u{0}');
+ check('\u{1}');
+ check('\u{12}');
+ check('\u{123}');
+ check('\u{1234}');
+ check('\u{12340}');
+ check('\u{10FFFF}');
+}
+
+#[test]
+fn test_decode_utf8() {
+ macro_rules! assert_decode_utf8 {
+ ($input_bytes: expr, $expected_str: expr) => {
+ let input_bytes: &[u8] = &$input_bytes;
+ let s = char::decode_utf8(input_bytes.iter().cloned())
+ .map(|r_b| r_b.unwrap_or('\u{FFFD}'))
+ .collect::<String>();
+ assert_eq!(s, $expected_str,
+ "input bytes: {:?}, expected str: {:?}, result: {:?}",
+ input_bytes, $expected_str, s);
+ assert_eq!(String::from_utf8_lossy(&$input_bytes), $expected_str);
+ }
+ }
+
+ assert_decode_utf8!([], "");
+ assert_decode_utf8!([0x41], "A");
+ assert_decode_utf8!([0xC1, 0x81], "��");
+ assert_decode_utf8!([0xE2, 0x99, 0xA5], "♥");
+ assert_decode_utf8!([0xE2, 0x99, 0xA5, 0x41], "♥A");
+ assert_decode_utf8!([0xE2, 0x99], "�");
+ assert_decode_utf8!([0xE2, 0x99, 0x41], "�A");
+ assert_decode_utf8!([0xC0], "�");
+ assert_decode_utf8!([0xC0, 0x41], "�A");
+ assert_decode_utf8!([0x80], "�");
+ assert_decode_utf8!([0x80, 0x41], "�A");
+ assert_decode_utf8!([0xFE], "�");
+ assert_decode_utf8!([0xFE, 0x41], "�A");
+ assert_decode_utf8!([0xFF], "�");
+ assert_decode_utf8!([0xFF, 0x41], "�A");
+ assert_decode_utf8!([0xC0, 0x80], "��");
+
+ // Surrogates
+ assert_decode_utf8!([0xED, 0x9F, 0xBF], "\u{D7FF}");
+ assert_decode_utf8!([0xED, 0xA0, 0x80], "���");
+ assert_decode_utf8!([0xED, 0xBF, 0x80], "���");
+ assert_decode_utf8!([0xEE, 0x80, 0x80], "\u{E000}");
+
+ // char::MAX
+ assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0xBF], "\u{10FFFF}");
+ assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0x41], "�A");
+ assert_decode_utf8!([0xF4, 0x90, 0x80, 0x80], "����");
+
+ // 5 and 6 bytes sequence
+ // Part of the original design of UTF-8,
+ // but invalid now that UTF-8 is artificially restricted to match the range of UTF-16.
+ assert_decode_utf8!([0xF8, 0x80, 0x80, 0x80, 0x80], "�����");
+ assert_decode_utf8!([0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], "������");
+}
--- /dev/null
+// Copyright 2014-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.
+
+#[test]
+fn test_borrowed_clone() {
+ let x = 5;
+ let y: &i32 = &x;
+ let z: &i32 = (&y).clone();
+ assert_eq!(*z, 5);
+}
+
+#[test]
+fn test_clone_from() {
+ let a = box 5;
+ let mut b = box 10;
+ b.clone_from(&a);
+ assert_eq!(*b, 5);
+}
--- /dev/null
+// Copyright 2014 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.
+
+use core::cmp::Ordering::{Less, Greater, Equal};
+
+#[test]
+fn test_int_totalord() {
+ assert_eq!(5.cmp(&10), Less);
+ assert_eq!(10.cmp(&5), Greater);
+ assert_eq!(5.cmp(&5), Equal);
+ assert_eq!((-5).cmp(&12), Less);
+ assert_eq!(12.cmp(&-5), Greater);
+}
+
+#[test]
+fn test_mut_int_totalord() {
+ assert_eq!((&mut 5).cmp(&&mut 10), Less);
+ assert_eq!((&mut 10).cmp(&&mut 5), Greater);
+ assert_eq!((&mut 5).cmp(&&mut 5), Equal);
+ assert_eq!((&mut -5).cmp(&&mut 12), Less);
+ assert_eq!((&mut 12).cmp(&&mut -5), Greater);
+}
+
+#[test]
+fn test_ordering_reverse() {
+ assert_eq!(Less.reverse(), Greater);
+ assert_eq!(Equal.reverse(), Equal);
+ assert_eq!(Greater.reverse(), Less);
+}
+
+#[test]
+fn test_ordering_order() {
+ assert!(Less < Equal);
+ assert_eq!(Greater.cmp(&Less), Greater);
+}
+
+#[test]
+fn test_ordering_then() {
+ assert_eq!(Equal.then(Less), Less);
+ assert_eq!(Equal.then(Equal), Equal);
+ assert_eq!(Equal.then(Greater), Greater);
+ assert_eq!(Less.then(Less), Less);
+ assert_eq!(Less.then(Equal), Less);
+ assert_eq!(Less.then(Greater), Less);
+ assert_eq!(Greater.then(Less), Greater);
+ assert_eq!(Greater.then(Equal), Greater);
+ assert_eq!(Greater.then(Greater), Greater);
+}
+
+#[test]
+fn test_ordering_then_with() {
+ assert_eq!(Equal.then_with(|| Less), Less);
+ assert_eq!(Equal.then_with(|| Equal), Equal);
+ assert_eq!(Equal.then_with(|| Greater), Greater);
+ assert_eq!(Less.then_with(|| Less), Less);
+ assert_eq!(Less.then_with(|| Equal), Less);
+ assert_eq!(Less.then_with(|| Greater), Less);
+ assert_eq!(Greater.then_with(|| Less), Greater);
+ assert_eq!(Greater.then_with(|| Equal), Greater);
+ assert_eq!(Greater.then_with(|| Greater), Greater);
+}
+
+#[test]
+fn test_user_defined_eq() {
+ // Our type.
+ struct SketchyNum {
+ num : isize
+ }
+
+ // Our implementation of `PartialEq` to support `==` and `!=`.
+ impl PartialEq for SketchyNum {
+ // Our custom eq allows numbers which are near each other to be equal! :D
+ fn eq(&self, other: &SketchyNum) -> bool {
+ (self.num - other.num).abs() < 5
+ }
+ }
+
+ // Now these binary operators will work when applied!
+ assert!(SketchyNum {num: 37} == SketchyNum {num: 34});
+ assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
+}
--- /dev/null
+// Copyright 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.
+
+mod debug_struct {
+ use std::fmt;
+
+ #[test]
+ fn test_empty() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("Foo").finish()
+ }
+ }
+
+ assert_eq!("Foo", format!("{:?}", Foo));
+ assert_eq!("Foo", format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_single() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("Foo")
+ .field("bar", &true)
+ .finish()
+ }
+ }
+
+ assert_eq!("Foo { bar: true }", format!("{:?}", Foo));
+ assert_eq!(
+"Foo {
+ bar: true
+}",
+ format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_multiple() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("Foo")
+ .field("bar", &true)
+ .field("baz", &format_args!("{}/{}", 10, 20))
+ .finish()
+ }
+ }
+
+ assert_eq!("Foo { bar: true, baz: 10/20 }", format!("{:?}", Foo));
+ assert_eq!(
+"Foo {
+ bar: true,
+ baz: 10/20
+}",
+ format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_nested() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("Foo")
+ .field("bar", &true)
+ .field("baz", &format_args!("{}/{}", 10, 20))
+ .finish()
+ }
+ }
+
+ struct Bar;
+
+ impl fmt::Debug for Bar {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("Bar")
+ .field("foo", &Foo)
+ .field("hello", &"world")
+ .finish()
+ }
+ }
+
+ assert_eq!("Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }",
+ format!("{:?}", Bar));
+ assert_eq!(
+"Bar {
+ foo: Foo {
+ bar: true,
+ baz: 10/20
+ },
+ hello: \"world\"
+}",
+ format!("{:#?}", Bar));
+ }
+}
+
+mod debug_tuple {
+ use std::fmt;
+
+ #[test]
+ fn test_empty() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_tuple("Foo").finish()
+ }
+ }
+
+ assert_eq!("Foo", format!("{:?}", Foo));
+ assert_eq!("Foo", format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_single() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_tuple("Foo")
+ .field(&true)
+ .finish()
+ }
+ }
+
+ assert_eq!("Foo(true)", format!("{:?}", Foo));
+ assert_eq!(
+"Foo(
+ true
+)",
+ format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_multiple() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_tuple("Foo")
+ .field(&true)
+ .field(&format_args!("{}/{}", 10, 20))
+ .finish()
+ }
+ }
+
+ assert_eq!("Foo(true, 10/20)", format!("{:?}", Foo));
+ assert_eq!(
+"Foo(
+ true,
+ 10/20
+)",
+ format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_nested() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_tuple("Foo")
+ .field(&true)
+ .field(&format_args!("{}/{}", 10, 20))
+ .finish()
+ }
+ }
+
+ struct Bar;
+
+ impl fmt::Debug for Bar {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_tuple("Bar")
+ .field(&Foo)
+ .field(&"world")
+ .finish()
+ }
+ }
+
+ assert_eq!("Bar(Foo(true, 10/20), \"world\")",
+ format!("{:?}", Bar));
+ assert_eq!(
+"Bar(
+ Foo(
+ true,
+ 10/20
+ ),
+ \"world\"
+)",
+ format!("{:#?}", Bar));
+ }
+}
+
+mod debug_map {
+ use std::fmt;
+
+ #[test]
+ fn test_empty() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_map().finish()
+ }
+ }
+
+ assert_eq!("{}", format!("{:?}", Foo));
+ assert_eq!("{}", format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_single() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_map()
+ .entry(&"bar", &true)
+ .finish()
+ }
+ }
+
+ assert_eq!("{\"bar\": true}", format!("{:?}", Foo));
+ assert_eq!(
+"{
+ \"bar\": true
+}",
+ format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_multiple() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_map()
+ .entry(&"bar", &true)
+ .entry(&10, &format_args!("{}/{}", 10, 20))
+ .finish()
+ }
+ }
+
+ assert_eq!("{\"bar\": true, 10: 10/20}", format!("{:?}", Foo));
+ assert_eq!(
+"{
+ \"bar\": true,
+ 10: 10/20
+}",
+ format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_nested() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_map()
+ .entry(&"bar", &true)
+ .entry(&10, &format_args!("{}/{}", 10, 20))
+ .finish()
+ }
+ }
+
+ struct Bar;
+
+ impl fmt::Debug for Bar {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_map()
+ .entry(&"foo", &Foo)
+ .entry(&Foo, &"world")
+ .finish()
+ }
+ }
+
+ assert_eq!("{\"foo\": {\"bar\": true, 10: 10/20}, \
+ {\"bar\": true, 10: 10/20}: \"world\"}",
+ format!("{:?}", Bar));
+ assert_eq!(
+"{
+ \"foo\": {
+ \"bar\": true,
+ 10: 10/20
+ },
+ {
+ \"bar\": true,
+ 10: 10/20
+ }: \"world\"
+}",
+ format!("{:#?}", Bar));
+ }
+}
+
+mod debug_set {
+ use std::fmt;
+
+ #[test]
+ fn test_empty() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_set().finish()
+ }
+ }
+
+ assert_eq!("{}", format!("{:?}", Foo));
+ assert_eq!("{}", format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_single() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_set()
+ .entry(&true)
+ .finish()
+ }
+ }
+
+ assert_eq!("{true}", format!("{:?}", Foo));
+ assert_eq!(
+"{
+ true
+}",
+ format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_multiple() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_set()
+ .entry(&true)
+ .entry(&format_args!("{}/{}", 10, 20))
+ .finish()
+ }
+ }
+
+ assert_eq!("{true, 10/20}", format!("{:?}", Foo));
+ assert_eq!(
+"{
+ true,
+ 10/20
+}",
+ format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_nested() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_set()
+ .entry(&true)
+ .entry(&format_args!("{}/{}", 10, 20))
+ .finish()
+ }
+ }
+
+ struct Bar;
+
+ impl fmt::Debug for Bar {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_set()
+ .entry(&Foo)
+ .entry(&"world")
+ .finish()
+ }
+ }
+
+ assert_eq!("{{true, 10/20}, \"world\"}",
+ format!("{:?}", Bar));
+ assert_eq!(
+"{
+ {
+ true,
+ 10/20
+ },
+ \"world\"
+}",
+ format!("{:#?}", Bar));
+ }
+}
+
+mod debug_list {
+ use std::fmt;
+
+ #[test]
+ fn test_empty() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_list().finish()
+ }
+ }
+
+ assert_eq!("[]", format!("{:?}", Foo));
+ assert_eq!("[]", format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_single() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_list()
+ .entry(&true)
+ .finish()
+ }
+ }
+
+ assert_eq!("[true]", format!("{:?}", Foo));
+ assert_eq!(
+"[
+ true
+]",
+ format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_multiple() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_list()
+ .entry(&true)
+ .entry(&format_args!("{}/{}", 10, 20))
+ .finish()
+ }
+ }
+
+ assert_eq!("[true, 10/20]", format!("{:?}", Foo));
+ assert_eq!(
+"[
+ true,
+ 10/20
+]",
+ format!("{:#?}", Foo));
+ }
+
+ #[test]
+ fn test_nested() {
+ struct Foo;
+
+ impl fmt::Debug for Foo {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_list()
+ .entry(&true)
+ .entry(&format_args!("{}/{}", 10, 20))
+ .finish()
+ }
+ }
+
+ struct Bar;
+
+ impl fmt::Debug for Bar {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_list()
+ .entry(&Foo)
+ .entry(&"world")
+ .finish()
+ }
+ }
+
+ assert_eq!("[[true, 10/20], \"world\"]",
+ format!("{:?}", Bar));
+ assert_eq!(
+"[
+ [
+ true,
+ 10/20
+ ],
+ \"world\"
+]",
+ format!("{:#?}", Bar));
+ }
+}
--- /dev/null
+// Copyright 2014 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.
+
+#[test]
+fn test_format_f64() {
+ assert_eq!("1", format!("{:.0}", 1.0f64));
+ assert_eq!("9", format!("{:.0}", 9.4f64));
+ assert_eq!("10", format!("{:.0}", 9.9f64));
+ assert_eq!("9.8", format!("{:.1}", 9.849f64));
+ assert_eq!("9.9", format!("{:.1}", 9.851f64));
+ assert_eq!("1", format!("{:.0}", 0.5f64));
+ assert_eq!("1.23456789e6", format!("{:e}", 1234567.89f64));
+ assert_eq!("1.23456789e3", format!("{:e}", 1234.56789f64));
+ assert_eq!("1.23456789E6", format!("{:E}", 1234567.89f64));
+ assert_eq!("1.23456789E3", format!("{:E}", 1234.56789f64));
+}
+
+#[test]
+fn test_format_f32() {
+ assert_eq!("1", format!("{:.0}", 1.0f32));
+ assert_eq!("9", format!("{:.0}", 9.4f32));
+ assert_eq!("10", format!("{:.0}", 9.9f32));
+ assert_eq!("9.8", format!("{:.1}", 9.849f32));
+ assert_eq!("9.9", format!("{:.1}", 9.851f32));
+ assert_eq!("1", format!("{:.0}", 0.5f32));
+ assert_eq!("1.2345679e6", format!("{:e}", 1234567.89f32));
+ assert_eq!("1.2345679e3", format!("{:e}", 1234.56789f32));
+ assert_eq!("1.2345679E6", format!("{:E}", 1234567.89f32));
+ assert_eq!("1.2345679E3", format!("{:E}", 1234.56789f32));
+}
--- /dev/null
+// Copyright 2014 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.
+
+mod builders;
+mod float;
+mod num;
+
+#[test]
+fn test_format_flags() {
+ // No residual flags left by pointer formatting
+ let p = "".as_ptr();
+ assert_eq!(format!("{:p} {:x}", p, 16), format!("{:p} 10", p));
+
+ assert_eq!(format!("{: >3}", 'a'), " a");
+}
+
+#[test]
+fn test_pointer_formats_data_pointer() {
+ let b: &[u8] = b"";
+ let s: &str = "";
+ assert_eq!(format!("{:p}", s), format!("{:p}", s.as_ptr()));
+ assert_eq!(format!("{:p}", b), format!("{:p}", b.as_ptr()));
+}
+
+#[test]
+fn test_estimated_capacity() {
+ assert_eq!(format_args!("").estimated_capacity(), 0);
+ assert_eq!(format_args!("{}", "").estimated_capacity(), 0);
+ assert_eq!(format_args!("Hello").estimated_capacity(), 5);
+ assert_eq!(format_args!("Hello, {}!", "").estimated_capacity(), 16);
+ assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0);
+ assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32);
+}
--- /dev/null
+// Copyright 2014 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.
+
+#[test]
+fn test_format_int() {
+ // Formatting integers should select the right implementation based off
+ // the type of the argument. Also, hex/octal/binary should be defined
+ // for integers, but they shouldn't emit the negative sign.
+ assert!(format!("{}", 1isize) == "1");
+ assert!(format!("{}", 1i8) == "1");
+ assert!(format!("{}", 1i16) == "1");
+ assert!(format!("{}", 1i32) == "1");
+ assert!(format!("{}", 1i64) == "1");
+ assert!(format!("{}", -1isize) == "-1");
+ assert!(format!("{}", -1i8) == "-1");
+ assert!(format!("{}", -1i16) == "-1");
+ assert!(format!("{}", -1i32) == "-1");
+ assert!(format!("{}", -1i64) == "-1");
+ assert!(format!("{:?}", 1isize) == "1");
+ assert!(format!("{:?}", 1i8) == "1");
+ assert!(format!("{:?}", 1i16) == "1");
+ assert!(format!("{:?}", 1i32) == "1");
+ assert!(format!("{:?}", 1i64) == "1");
+ assert!(format!("{:b}", 1isize) == "1");
+ assert!(format!("{:b}", 1i8) == "1");
+ assert!(format!("{:b}", 1i16) == "1");
+ assert!(format!("{:b}", 1i32) == "1");
+ assert!(format!("{:b}", 1i64) == "1");
+ assert!(format!("{:x}", 1isize) == "1");
+ assert!(format!("{:x}", 1i8) == "1");
+ assert!(format!("{:x}", 1i16) == "1");
+ assert!(format!("{:x}", 1i32) == "1");
+ assert!(format!("{:x}", 1i64) == "1");
+ assert!(format!("{:X}", 1isize) == "1");
+ assert!(format!("{:X}", 1i8) == "1");
+ assert!(format!("{:X}", 1i16) == "1");
+ assert!(format!("{:X}", 1i32) == "1");
+ assert!(format!("{:X}", 1i64) == "1");
+ assert!(format!("{:o}", 1isize) == "1");
+ assert!(format!("{:o}", 1i8) == "1");
+ assert!(format!("{:o}", 1i16) == "1");
+ assert!(format!("{:o}", 1i32) == "1");
+ assert!(format!("{:o}", 1i64) == "1");
+
+ assert!(format!("{}", 1usize) == "1");
+ assert!(format!("{}", 1u8) == "1");
+ assert!(format!("{}", 1u16) == "1");
+ assert!(format!("{}", 1u32) == "1");
+ assert!(format!("{}", 1u64) == "1");
+ assert!(format!("{:?}", 1usize) == "1");
+ assert!(format!("{:?}", 1u8) == "1");
+ assert!(format!("{:?}", 1u16) == "1");
+ assert!(format!("{:?}", 1u32) == "1");
+ assert!(format!("{:?}", 1u64) == "1");
+ assert!(format!("{:b}", 1usize) == "1");
+ assert!(format!("{:b}", 1u8) == "1");
+ assert!(format!("{:b}", 1u16) == "1");
+ assert!(format!("{:b}", 1u32) == "1");
+ assert!(format!("{:b}", 1u64) == "1");
+ assert!(format!("{:x}", 1usize) == "1");
+ assert!(format!("{:x}", 1u8) == "1");
+ assert!(format!("{:x}", 1u16) == "1");
+ assert!(format!("{:x}", 1u32) == "1");
+ assert!(format!("{:x}", 1u64) == "1");
+ assert!(format!("{:X}", 1usize) == "1");
+ assert!(format!("{:X}", 1u8) == "1");
+ assert!(format!("{:X}", 1u16) == "1");
+ assert!(format!("{:X}", 1u32) == "1");
+ assert!(format!("{:X}", 1u64) == "1");
+ assert!(format!("{:o}", 1usize) == "1");
+ assert!(format!("{:o}", 1u8) == "1");
+ assert!(format!("{:o}", 1u16) == "1");
+ assert!(format!("{:o}", 1u32) == "1");
+ assert!(format!("{:o}", 1u64) == "1");
+
+ // Test a larger number
+ assert!(format!("{:b}", 55) == "110111");
+ assert!(format!("{:o}", 55) == "67");
+ assert!(format!("{}", 55) == "55");
+ assert!(format!("{:x}", 55) == "37");
+ assert!(format!("{:X}", 55) == "37");
+}
+
+#[test]
+fn test_format_int_zero() {
+ assert!(format!("{}", 0) == "0");
+ assert!(format!("{:?}", 0) == "0");
+ assert!(format!("{:b}", 0) == "0");
+ assert!(format!("{:o}", 0) == "0");
+ assert!(format!("{:x}", 0) == "0");
+ assert!(format!("{:X}", 0) == "0");
+
+ assert!(format!("{}", 0u32) == "0");
+ assert!(format!("{:?}", 0u32) == "0");
+ assert!(format!("{:b}", 0u32) == "0");
+ assert!(format!("{:o}", 0u32) == "0");
+ assert!(format!("{:x}", 0u32) == "0");
+ assert!(format!("{:X}", 0u32) == "0");
+}
+
+#[test]
+fn test_format_int_flags() {
+ assert!(format!("{:3}", 1) == " 1");
+ assert!(format!("{:>3}", 1) == " 1");
+ assert!(format!("{:>+3}", 1) == " +1");
+ assert!(format!("{:<3}", 1) == "1 ");
+ assert!(format!("{:#}", 1) == "1");
+ assert!(format!("{:#x}", 10) == "0xa");
+ assert!(format!("{:#X}", 10) == "0xA");
+ assert!(format!("{:#5x}", 10) == " 0xa");
+ assert!(format!("{:#o}", 10) == "0o12");
+ assert!(format!("{:08x}", 10) == "0000000a");
+ assert!(format!("{:8x}", 10) == " a");
+ assert!(format!("{:<8x}", 10) == "a ");
+ assert!(format!("{:>8x}", 10) == " a");
+ assert!(format!("{:#08x}", 10) == "0x00000a");
+ assert!(format!("{:08}", -10) == "-0000010");
+ assert!(format!("{:x}", !0u8) == "ff");
+ assert!(format!("{:X}", !0u8) == "FF");
+ assert!(format!("{:b}", !0u8) == "11111111");
+ assert!(format!("{:o}", !0u8) == "377");
+ assert!(format!("{:#x}", !0u8) == "0xff");
+ assert!(format!("{:#X}", !0u8) == "0xFF");
+ assert!(format!("{:#b}", !0u8) == "0b11111111");
+ assert!(format!("{:#o}", !0u8) == "0o377");
+}
+
+#[test]
+fn test_format_int_sign_padding() {
+ assert!(format!("{:+5}", 1) == " +1");
+ assert!(format!("{:+5}", -1) == " -1");
+ assert!(format!("{:05}", 1) == "00001");
+ assert!(format!("{:05}", -1) == "-0001");
+ assert!(format!("{:+05}", 1) == "+0001");
+ assert!(format!("{:+05}", -1) == "-0001");
+}
+
+#[test]
+fn test_format_int_twos_complement() {
+ use core::{i8, i16, i32, i64};
+ assert!(format!("{}", i8::MIN) == "-128");
+ assert!(format!("{}", i16::MIN) == "-32768");
+ assert!(format!("{}", i32::MIN) == "-2147483648");
+ assert!(format!("{}", i64::MIN) == "-9223372036854775808");
+}
--- /dev/null
+// Copyright 2014 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.
+
+mod sip;
+
+use std::hash::{Hash, Hasher};
+use std::default::Default;
+
+struct MyHasher {
+ hash: u64,
+}
+
+impl Default for MyHasher {
+ fn default() -> MyHasher {
+ MyHasher { hash: 0 }
+ }
+}
+
+impl Hasher for MyHasher {
+ fn write(&mut self, buf: &[u8]) {
+ for byte in buf {
+ self.hash += *byte as u64;
+ }
+ }
+ fn finish(&self) -> u64 { self.hash }
+}
+
+
+#[test]
+fn test_writer_hasher() {
+ fn hash<T: Hash>(t: &T) -> u64 {
+ let mut s = MyHasher { hash: 0 };
+ t.hash(&mut s);
+ s.finish()
+ }
+
+ assert_eq!(hash(&()), 0);
+
+ assert_eq!(hash(&5_u8), 5);
+ assert_eq!(hash(&5_u16), 5);
+ assert_eq!(hash(&5_u32), 5);
+ assert_eq!(hash(&5_u64), 5);
+ assert_eq!(hash(&5_usize), 5);
+
+ assert_eq!(hash(&5_i8), 5);
+ assert_eq!(hash(&5_i16), 5);
+ assert_eq!(hash(&5_i32), 5);
+ assert_eq!(hash(&5_i64), 5);
+ assert_eq!(hash(&5_isize), 5);
+
+ assert_eq!(hash(&false), 0);
+ assert_eq!(hash(&true), 1);
+
+ assert_eq!(hash(&'a'), 97);
+
+ let s: &str = "a";
+ assert_eq!(hash(& s), 97 + 0xFF);
+ let s: Box<str> = String::from("a").into_boxed_str();
+ assert_eq!(hash(& s), 97 + 0xFF);
+ let cs: &[u8] = &[1, 2, 3];
+ assert_eq!(hash(& cs), 9);
+ let cs: Box<[u8]> = Box::new([1, 2, 3]);
+ assert_eq!(hash(& cs), 9);
+
+ // FIXME (#18248) Add tests for hashing Rc<str> and Rc<[T]>
+
+ let ptr = 5_usize as *const i32;
+ assert_eq!(hash(&ptr), 5);
+
+ let ptr = 5_usize as *mut i32;
+ assert_eq!(hash(&ptr), 5);
+}
+
+struct Custom { hash: u64 }
+struct CustomHasher { output: u64 }
+
+impl Hasher for CustomHasher {
+ fn finish(&self) -> u64 { self.output }
+ fn write(&mut self, _: &[u8]) { panic!() }
+ fn write_u64(&mut self, data: u64) { self.output = data; }
+}
+
+impl Default for CustomHasher {
+ fn default() -> CustomHasher {
+ CustomHasher { output: 0 }
+ }
+}
+
+impl Hash for Custom {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.write_u64(self.hash);
+ }
+}
+
+#[test]
+fn test_custom_state() {
+ fn hash<T: Hash>(t: &T) -> u64 {
+ let mut c = CustomHasher { output: 0 };
+ t.hash(&mut c);
+ c.finish()
+ }
+
+ assert_eq!(hash(&Custom { hash: 5 }), 5);
+}
--- /dev/null
+// Copyright 2014 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.
+
+#![allow(deprecated)]
+
+use core::hash::{Hash, Hasher};
+use core::hash::{SipHasher, SipHasher13, SipHasher24};
+use core::{slice, mem};
+
+// Hash just the bytes of the slice, without length prefix
+struct Bytes<'a>(&'a [u8]);
+
+impl<'a> Hash for Bytes<'a> {
+ #[allow(unused_must_use)]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ let Bytes(v) = *self;
+ state.write(v);
+ }
+}
+
+macro_rules! u8to64_le {
+ ($buf:expr, $i:expr) =>
+ ($buf[0+$i] as u64 |
+ ($buf[1+$i] as u64) << 8 |
+ ($buf[2+$i] as u64) << 16 |
+ ($buf[3+$i] as u64) << 24 |
+ ($buf[4+$i] as u64) << 32 |
+ ($buf[5+$i] as u64) << 40 |
+ ($buf[6+$i] as u64) << 48 |
+ ($buf[7+$i] as u64) << 56);
+ ($buf:expr, $i:expr, $len:expr) =>
+ ({
+ let mut t = 0;
+ let mut out = 0;
+ while t < $len {
+ out |= ($buf[t+$i] as u64) << t*8;
+ t += 1;
+ }
+ out
+ });
+}
+
+fn hash_with<H: Hasher, T: Hash>(mut st: H, x: &T) -> u64 {
+ x.hash(&mut st);
+ st.finish()
+}
+
+fn hash<T: Hash>(x: &T) -> u64 {
+ hash_with(SipHasher::new(), x)
+}
+
+#[test]
+#[allow(unused_must_use)]
+fn test_siphash_1_3() {
+ let vecs : [[u8; 8]; 64] = [
+ [ 0xdc, 0xc4, 0x0f, 0x05, 0x58, 0x01, 0xac, 0xab ],
+ [ 0x93, 0xca, 0x57, 0x7d, 0xf3, 0x9b, 0xf4, 0xc9 ],
+ [ 0x4d, 0xd4, 0xc7, 0x4d, 0x02, 0x9b, 0xcb, 0x82 ],
+ [ 0xfb, 0xf7, 0xdd, 0xe7, 0xb8, 0x0a, 0xf8, 0x8b ],
+ [ 0x28, 0x83, 0xd3, 0x88, 0x60, 0x57, 0x75, 0xcf ],
+ [ 0x67, 0x3b, 0x53, 0x49, 0x2f, 0xd5, 0xf9, 0xde ],
+ [ 0xa7, 0x22, 0x9f, 0xc5, 0x50, 0x2b, 0x0d, 0xc5 ],
+ [ 0x40, 0x11, 0xb1, 0x9b, 0x98, 0x7d, 0x92, 0xd3 ],
+ [ 0x8e, 0x9a, 0x29, 0x8d, 0x11, 0x95, 0x90, 0x36 ],
+ [ 0xe4, 0x3d, 0x06, 0x6c, 0xb3, 0x8e, 0xa4, 0x25 ],
+ [ 0x7f, 0x09, 0xff, 0x92, 0xee, 0x85, 0xde, 0x79 ],
+ [ 0x52, 0xc3, 0x4d, 0xf9, 0xc1, 0x18, 0xc1, 0x70 ],
+ [ 0xa2, 0xd9, 0xb4, 0x57, 0xb1, 0x84, 0xa3, 0x78 ],
+ [ 0xa7, 0xff, 0x29, 0x12, 0x0c, 0x76, 0x6f, 0x30 ],
+ [ 0x34, 0x5d, 0xf9, 0xc0, 0x11, 0xa1, 0x5a, 0x60 ],
+ [ 0x56, 0x99, 0x51, 0x2a, 0x6d, 0xd8, 0x20, 0xd3 ],
+ [ 0x66, 0x8b, 0x90, 0x7d, 0x1a, 0xdd, 0x4f, 0xcc ],
+ [ 0x0c, 0xd8, 0xdb, 0x63, 0x90, 0x68, 0xf2, 0x9c ],
+ [ 0x3e, 0xe6, 0x73, 0xb4, 0x9c, 0x38, 0xfc, 0x8f ],
+ [ 0x1c, 0x7d, 0x29, 0x8d, 0xe5, 0x9d, 0x1f, 0xf2 ],
+ [ 0x40, 0xe0, 0xcc, 0xa6, 0x46, 0x2f, 0xdc, 0xc0 ],
+ [ 0x44, 0xf8, 0x45, 0x2b, 0xfe, 0xab, 0x92, 0xb9 ],
+ [ 0x2e, 0x87, 0x20, 0xa3, 0x9b, 0x7b, 0xfe, 0x7f ],
+ [ 0x23, 0xc1, 0xe6, 0xda, 0x7f, 0x0e, 0x5a, 0x52 ],
+ [ 0x8c, 0x9c, 0x34, 0x67, 0xb2, 0xae, 0x64, 0xf4 ],
+ [ 0x79, 0x09, 0x5b, 0x70, 0x28, 0x59, 0xcd, 0x45 ],
+ [ 0xa5, 0x13, 0x99, 0xca, 0xe3, 0x35, 0x3e, 0x3a ],
+ [ 0x35, 0x3b, 0xde, 0x4a, 0x4e, 0xc7, 0x1d, 0xa9 ],
+ [ 0x0d, 0xd0, 0x6c, 0xef, 0x02, 0xed, 0x0b, 0xfb ],
+ [ 0xf4, 0xe1, 0xb1, 0x4a, 0xb4, 0x3c, 0xd9, 0x88 ],
+ [ 0x63, 0xe6, 0xc5, 0x43, 0xd6, 0x11, 0x0f, 0x54 ],
+ [ 0xbc, 0xd1, 0x21, 0x8c, 0x1f, 0xdd, 0x70, 0x23 ],
+ [ 0x0d, 0xb6, 0xa7, 0x16, 0x6c, 0x7b, 0x15, 0x81 ],
+ [ 0xbf, 0xf9, 0x8f, 0x7a, 0xe5, 0xb9, 0x54, 0x4d ],
+ [ 0x3e, 0x75, 0x2a, 0x1f, 0x78, 0x12, 0x9f, 0x75 ],
+ [ 0x91, 0x6b, 0x18, 0xbf, 0xbe, 0xa3, 0xa1, 0xce ],
+ [ 0x06, 0x62, 0xa2, 0xad, 0xd3, 0x08, 0xf5, 0x2c ],
+ [ 0x57, 0x30, 0xc3, 0xa3, 0x2d, 0x1c, 0x10, 0xb6 ],
+ [ 0xa1, 0x36, 0x3a, 0xae, 0x96, 0x74, 0xf4, 0xb3 ],
+ [ 0x92, 0x83, 0x10, 0x7b, 0x54, 0x57, 0x6b, 0x62 ],
+ [ 0x31, 0x15, 0xe4, 0x99, 0x32, 0x36, 0xd2, 0xc1 ],
+ [ 0x44, 0xd9, 0x1a, 0x3f, 0x92, 0xc1, 0x7c, 0x66 ],
+ [ 0x25, 0x88, 0x13, 0xc8, 0xfe, 0x4f, 0x70, 0x65 ],
+ [ 0xa6, 0x49, 0x89, 0xc2, 0xd1, 0x80, 0xf2, 0x24 ],
+ [ 0x6b, 0x87, 0xf8, 0xfa, 0xed, 0x1c, 0xca, 0xc2 ],
+ [ 0x96, 0x21, 0x04, 0x9f, 0xfc, 0x4b, 0x16, 0xc2 ],
+ [ 0x23, 0xd6, 0xb1, 0x68, 0x93, 0x9c, 0x6e, 0xa1 ],
+ [ 0xfd, 0x14, 0x51, 0x8b, 0x9c, 0x16, 0xfb, 0x49 ],
+ [ 0x46, 0x4c, 0x07, 0xdf, 0xf8, 0x43, 0x31, 0x9f ],
+ [ 0xb3, 0x86, 0xcc, 0x12, 0x24, 0xaf, 0xfd, 0xc6 ],
+ [ 0x8f, 0x09, 0x52, 0x0a, 0xd1, 0x49, 0xaf, 0x7e ],
+ [ 0x9a, 0x2f, 0x29, 0x9d, 0x55, 0x13, 0xf3, 0x1c ],
+ [ 0x12, 0x1f, 0xf4, 0xa2, 0xdd, 0x30, 0x4a, 0xc4 ],
+ [ 0xd0, 0x1e, 0xa7, 0x43, 0x89, 0xe9, 0xfa, 0x36 ],
+ [ 0xe6, 0xbc, 0xf0, 0x73, 0x4c, 0xb3, 0x8f, 0x31 ],
+ [ 0x80, 0xe9, 0xa7, 0x70, 0x36, 0xbf, 0x7a, 0xa2 ],
+ [ 0x75, 0x6d, 0x3c, 0x24, 0xdb, 0xc0, 0xbc, 0xb4 ],
+ [ 0x13, 0x15, 0xb7, 0xfd, 0x52, 0xd8, 0xf8, 0x23 ],
+ [ 0x08, 0x8a, 0x7d, 0xa6, 0x4d, 0x5f, 0x03, 0x8f ],
+ [ 0x48, 0xf1, 0xe8, 0xb7, 0xe5, 0xd0, 0x9c, 0xd8 ],
+ [ 0xee, 0x44, 0xa6, 0xf7, 0xbc, 0xe6, 0xf4, 0xf6 ],
+ [ 0xf2, 0x37, 0x18, 0x0f, 0xd8, 0x9a, 0xc5, 0xae ],
+ [ 0xe0, 0x94, 0x66, 0x4b, 0x15, 0xf6, 0xb2, 0xc3 ],
+ [ 0xa8, 0xb3, 0xbb, 0xb7, 0x62, 0x90, 0x19, 0x9d ]
+ ];
+
+ let k0 = 0x_07_06_05_04_03_02_01_00;
+ let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08;
+ let mut buf = Vec::new();
+ let mut t = 0;
+ let mut state_inc = SipHasher13::new_with_keys(k0, k1);
+
+ while t < 64 {
+ let vec = u8to64_le!(vecs[t], 0);
+ let out = hash_with(SipHasher13::new_with_keys(k0, k1), &Bytes(&buf));
+ assert_eq!(vec, out);
+
+ let full = hash_with(SipHasher13::new_with_keys(k0, k1), &Bytes(&buf));
+ let i = state_inc.finish();
+
+ assert_eq!(full, i);
+ assert_eq!(full, vec);
+
+ buf.push(t as u8);
+ Hasher::write(&mut state_inc, &[t as u8]);
+
+ t += 1;
+ }
+}
+
+#[test]
+#[allow(unused_must_use)]
+fn test_siphash_2_4() {
+ let vecs : [[u8; 8]; 64] = [
+ [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
+ [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
+ [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
+ [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ],
+ [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ],
+ [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ],
+ [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ],
+ [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ],
+ [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ],
+ [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ],
+ [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ],
+ [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ],
+ [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ],
+ [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ],
+ [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ],
+ [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ],
+ [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ],
+ [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ],
+ [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ],
+ [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ],
+ [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ],
+ [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ],
+ [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ],
+ [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ],
+ [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ],
+ [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ],
+ [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ],
+ [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ],
+ [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ],
+ [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ],
+ [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ],
+ [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ],
+ [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ],
+ [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ],
+ [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ],
+ [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ],
+ [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ],
+ [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ],
+ [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ],
+ [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ],
+ [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ],
+ [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ],
+ [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ],
+ [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ],
+ [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ],
+ [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ],
+ [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ],
+ [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ],
+ [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ],
+ [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ],
+ [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ],
+ [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ],
+ [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ],
+ [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ],
+ [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ],
+ [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ],
+ [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ],
+ [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ],
+ [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ],
+ [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ],
+ [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ],
+ [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ],
+ [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ],
+ [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]
+ ];
+
+ let k0 = 0x_07_06_05_04_03_02_01_00;
+ let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08;
+ let mut buf = Vec::new();
+ let mut t = 0;
+ let mut state_inc = SipHasher24::new_with_keys(k0, k1);
+
+ while t < 64 {
+ let vec = u8to64_le!(vecs[t], 0);
+ let out = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
+ assert_eq!(vec, out);
+
+ let full = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
+ let i = state_inc.finish();
+
+ assert_eq!(full, i);
+ assert_eq!(full, vec);
+
+ buf.push(t as u8);
+ Hasher::write(&mut state_inc, &[t as u8]);
+
+ t += 1;
+ }
+}
+#[test] #[cfg(target_arch = "arm")]
+fn test_hash_usize() {
+ let val = 0xdeadbeef_deadbeef_u64;
+ assert!(hash(&(val as u64)) != hash(&(val as usize)));
+ assert_eq!(hash(&(val as u32)), hash(&(val as usize)));
+}
+#[test] #[cfg(target_arch = "x86_64")]
+fn test_hash_usize() {
+ let val = 0xdeadbeef_deadbeef_u64;
+ assert_eq!(hash(&(val as u64)), hash(&(val as usize)));
+ assert!(hash(&(val as u32)) != hash(&(val as usize)));
+}
+#[test] #[cfg(target_arch = "x86")]
+fn test_hash_usize() {
+ let val = 0xdeadbeef_deadbeef_u64;
+ assert!(hash(&(val as u64)) != hash(&(val as usize)));
+ assert_eq!(hash(&(val as u32)), hash(&(val as usize)));
+}
+
+#[test]
+fn test_hash_idempotent() {
+ let val64 = 0xdeadbeef_deadbeef_u64;
+ assert_eq!(hash(&val64), hash(&val64));
+ let val32 = 0xdeadbeef_u32;
+ assert_eq!(hash(&val32), hash(&val32));
+}
+
+#[test]
+fn test_hash_no_bytes_dropped_64() {
+ let val = 0xdeadbeef_deadbeef_u64;
+
+ assert!(hash(&val) != hash(&zero_byte(val, 0)));
+ assert!(hash(&val) != hash(&zero_byte(val, 1)));
+ assert!(hash(&val) != hash(&zero_byte(val, 2)));
+ assert!(hash(&val) != hash(&zero_byte(val, 3)));
+ assert!(hash(&val) != hash(&zero_byte(val, 4)));
+ assert!(hash(&val) != hash(&zero_byte(val, 5)));
+ assert!(hash(&val) != hash(&zero_byte(val, 6)));
+ assert!(hash(&val) != hash(&zero_byte(val, 7)));
+
+ fn zero_byte(val: u64, byte: usize) -> u64 {
+ assert!(byte < 8);
+ val & !(0xff << (byte * 8))
+ }
+}
+
+#[test]
+fn test_hash_no_bytes_dropped_32() {
+ let val = 0xdeadbeef_u32;
+
+ assert!(hash(&val) != hash(&zero_byte(val, 0)));
+ assert!(hash(&val) != hash(&zero_byte(val, 1)));
+ assert!(hash(&val) != hash(&zero_byte(val, 2)));
+ assert!(hash(&val) != hash(&zero_byte(val, 3)));
+
+ fn zero_byte(val: u32, byte: usize) -> u32 {
+ assert!(byte < 4);
+ val & !(0xff << (byte * 8))
+ }
+}
+
+#[test]
+fn test_hash_no_concat_alias() {
+ let s = ("aa", "bb");
+ let t = ("aabb", "");
+ let u = ("a", "abb");
+
+ assert!(s != t && t != u);
+ assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u));
+
+ let u = [1, 0, 0, 0];
+ let v = (&u[..1], &u[1..3], &u[3..]);
+ let w = (&u[..], &u[4..4], &u[4..4]);
+
+ assert!(v != w);
+ assert!(hash(&v) != hash(&w));
+}
+
+#[test]
+fn test_write_short_works() {
+ let test_usize = 0xd0c0b0a0usize;
+ let mut h1 = SipHasher24::new();
+ h1.write_usize(test_usize);
+ h1.write(b"bytes");
+ h1.write(b"string");
+ h1.write_u8(0xFFu8);
+ h1.write_u8(0x01u8);
+ let mut h2 = SipHasher24::new();
+ h2.write(unsafe {
+ slice::from_raw_parts(&test_usize as *const _ as *const u8,
+ mem::size_of::<usize>())
+ });
+ h2.write(b"bytes");
+ h2.write(b"string");
+ h2.write(&[0xFFu8, 0x01u8]);
+ assert_eq!(h1.finish(), h2.finish());
+}
--- /dev/null
+// Copyright 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.
+
+use core::any::TypeId;
+
+#[test]
+fn test_typeid_sized_types() {
+ struct X; struct Y(u32);
+
+ assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
+ assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
+ assert!(TypeId::of::<X>() != TypeId::of::<Y>());
+}
+
+#[test]
+fn test_typeid_unsized_types() {
+ trait Z {}
+ struct X(str); struct Y(Z + 'static);
+
+ assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
+ assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
+ assert!(TypeId::of::<X>() != TypeId::of::<Y>());
+}
--- /dev/null
+// Copyright 2014 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.
+
+use core::iter::*;
+use core::{i8, i16, isize};
+use core::usize;
+
+#[test]
+fn test_lt() {
+ let empty: [isize; 0] = [];
+ let xs = [1,2,3];
+ let ys = [1,2,0];
+
+ assert!(!xs.iter().lt(ys.iter()));
+ assert!(!xs.iter().le(ys.iter()));
+ assert!( xs.iter().gt(ys.iter()));
+ assert!( xs.iter().ge(ys.iter()));
+
+ assert!( ys.iter().lt(xs.iter()));
+ assert!( ys.iter().le(xs.iter()));
+ assert!(!ys.iter().gt(xs.iter()));
+ assert!(!ys.iter().ge(xs.iter()));
+
+ assert!( empty.iter().lt(xs.iter()));
+ assert!( empty.iter().le(xs.iter()));
+ assert!(!empty.iter().gt(xs.iter()));
+ assert!(!empty.iter().ge(xs.iter()));
+
+ // Sequence with NaN
+ let u = [1.0f64, 2.0];
+ let v = [0.0f64/0.0, 3.0];
+
+ assert!(!u.iter().lt(v.iter()));
+ assert!(!u.iter().le(v.iter()));
+ assert!(!u.iter().gt(v.iter()));
+ assert!(!u.iter().ge(v.iter()));
+
+ let a = [0.0f64/0.0];
+ let b = [1.0f64];
+ let c = [2.0f64];
+
+ assert!(a.iter().lt(b.iter()) == (a[0] < b[0]));
+ assert!(a.iter().le(b.iter()) == (a[0] <= b[0]));
+ assert!(a.iter().gt(b.iter()) == (a[0] > b[0]));
+ assert!(a.iter().ge(b.iter()) == (a[0] >= b[0]));
+
+ assert!(c.iter().lt(b.iter()) == (c[0] < b[0]));
+ assert!(c.iter().le(b.iter()) == (c[0] <= b[0]));
+ assert!(c.iter().gt(b.iter()) == (c[0] > b[0]));
+ assert!(c.iter().ge(b.iter()) == (c[0] >= b[0]));
+}
+
+#[test]
+fn test_multi_iter() {
+ let xs = [1,2,3,4];
+ let ys = [4,3,2,1];
+ assert!(xs.iter().eq(ys.iter().rev()));
+ assert!(xs.iter().lt(xs.iter().skip(2)));
+}
+
+#[test]
+fn test_counter_from_iter() {
+ let it = (0..).step_by(5).take(10);
+ let xs: Vec<isize> = FromIterator::from_iter(it);
+ assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
+}
+
+#[test]
+fn test_iterator_chain() {
+ let xs = [0, 1, 2, 3, 4, 5];
+ let ys = [30, 40, 50, 60];
+ let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
+ let it = xs.iter().chain(&ys);
+ let mut i = 0;
+ for &x in it {
+ assert_eq!(x, expected[i]);
+ i += 1;
+ }
+ assert_eq!(i, expected.len());
+
+ let ys = (30..).step_by(10).take(4);
+ let it = xs.iter().cloned().chain(ys);
+ let mut i = 0;
+ for x in it {
+ assert_eq!(x, expected[i]);
+ i += 1;
+ }
+ assert_eq!(i, expected.len());
+}
+
+#[test]
+fn test_iterator_chain_nth() {
+ let xs = [0, 1, 2, 3, 4, 5];
+ let ys = [30, 40, 50, 60];
+ let zs = [];
+ let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
+ for (i, x) in expected.iter().enumerate() {
+ assert_eq!(Some(x), xs.iter().chain(&ys).nth(i));
+ }
+ assert_eq!(zs.iter().chain(&xs).nth(0), Some(&0));
+
+ let mut it = xs.iter().chain(&zs);
+ assert_eq!(it.nth(5), Some(&5));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_iterator_chain_last() {
+ let xs = [0, 1, 2, 3, 4, 5];
+ let ys = [30, 40, 50, 60];
+ let zs = [];
+ assert_eq!(xs.iter().chain(&ys).last(), Some(&60));
+ assert_eq!(zs.iter().chain(&ys).last(), Some(&60));
+ assert_eq!(ys.iter().chain(&zs).last(), Some(&60));
+ assert_eq!(zs.iter().chain(&zs).last(), None);
+}
+
+#[test]
+fn test_iterator_chain_count() {
+ let xs = [0, 1, 2, 3, 4, 5];
+ let ys = [30, 40, 50, 60];
+ let zs = [];
+ assert_eq!(xs.iter().chain(&ys).count(), 10);
+ assert_eq!(zs.iter().chain(&ys).count(), 4);
+}
+
+#[test]
+fn test_iterator_chain_find() {
+ let xs = [0, 1, 2, 3, 4, 5];
+ let ys = [30, 40, 50, 60];
+ let mut iter = xs.iter().chain(&ys);
+ assert_eq!(iter.find(|&&i| i == 4), Some(&4));
+ assert_eq!(iter.next(), Some(&5));
+ assert_eq!(iter.find(|&&i| i == 40), Some(&40));
+ assert_eq!(iter.next(), Some(&50));
+ assert_eq!(iter.find(|&&i| i == 100), None);
+ assert_eq!(iter.next(), None);
+}
+
+#[test]
+fn test_filter_map() {
+ let it = (0..).step_by(1).take(10)
+ .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
+ assert_eq!(it.collect::<Vec<usize>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
+}
+
+#[test]
+fn test_iterator_enumerate() {
+ let xs = [0, 1, 2, 3, 4, 5];
+ let it = xs.iter().enumerate();
+ for (i, &x) in it {
+ assert_eq!(i, x);
+ }
+}
+
+#[test]
+fn test_iterator_enumerate_nth() {
+ let xs = [0, 1, 2, 3, 4, 5];
+ for (i, &x) in xs.iter().enumerate() {
+ assert_eq!(i, x);
+ }
+
+ let mut it = xs.iter().enumerate();
+ while let Some((i, &x)) = it.nth(0) {
+ assert_eq!(i, x);
+ }
+
+ let mut it = xs.iter().enumerate();
+ while let Some((i, &x)) = it.nth(1) {
+ assert_eq!(i, x);
+ }
+
+ let (i, &x) = xs.iter().enumerate().nth(3).unwrap();
+ assert_eq!(i, x);
+ assert_eq!(i, 3);
+}
+
+#[test]
+fn test_iterator_enumerate_count() {
+ let xs = [0, 1, 2, 3, 4, 5];
+ assert_eq!(xs.iter().count(), 6);
+}
+
+#[test]
+fn test_iterator_filter_count() {
+ let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
+ assert_eq!(xs.iter().filter(|&&x| x % 2 == 0).count(), 5);
+}
+
+#[test]
+fn test_iterator_peekable() {
+ let xs = vec![0, 1, 2, 3, 4, 5];
+ let mut it = xs.iter().cloned().peekable();
+
+ assert_eq!(it.len(), 6);
+ assert_eq!(it.peek().unwrap(), &0);
+ assert_eq!(it.len(), 6);
+ assert_eq!(it.next().unwrap(), 0);
+ assert_eq!(it.len(), 5);
+ assert_eq!(it.next().unwrap(), 1);
+ assert_eq!(it.len(), 4);
+ assert_eq!(it.next().unwrap(), 2);
+ assert_eq!(it.len(), 3);
+ assert_eq!(it.peek().unwrap(), &3);
+ assert_eq!(it.len(), 3);
+ assert_eq!(it.peek().unwrap(), &3);
+ assert_eq!(it.len(), 3);
+ assert_eq!(it.next().unwrap(), 3);
+ assert_eq!(it.len(), 2);
+ assert_eq!(it.next().unwrap(), 4);
+ assert_eq!(it.len(), 1);
+ assert_eq!(it.peek().unwrap(), &5);
+ assert_eq!(it.len(), 1);
+ assert_eq!(it.next().unwrap(), 5);
+ assert_eq!(it.len(), 0);
+ assert!(it.peek().is_none());
+ assert_eq!(it.len(), 0);
+ assert!(it.next().is_none());
+ assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_peekable_count() {
+ let xs = [0, 1, 2, 3, 4, 5];
+ let ys = [10];
+ let zs: [i32; 0] = [];
+
+ assert_eq!(xs.iter().peekable().count(), 6);
+
+ let mut it = xs.iter().peekable();
+ assert_eq!(it.peek(), Some(&&0));
+ assert_eq!(it.count(), 6);
+
+ assert_eq!(ys.iter().peekable().count(), 1);
+
+ let mut it = ys.iter().peekable();
+ assert_eq!(it.peek(), Some(&&10));
+ assert_eq!(it.count(), 1);
+
+ assert_eq!(zs.iter().peekable().count(), 0);
+
+ let mut it = zs.iter().peekable();
+ assert_eq!(it.peek(), None);
+
+}
+
+#[test]
+fn test_iterator_peekable_nth() {
+ let xs = [0, 1, 2, 3, 4, 5];
+ let mut it = xs.iter().peekable();
+
+ assert_eq!(it.peek(), Some(&&0));
+ assert_eq!(it.nth(0), Some(&0));
+ assert_eq!(it.peek(), Some(&&1));
+ assert_eq!(it.nth(1), Some(&2));
+ assert_eq!(it.peek(), Some(&&3));
+ assert_eq!(it.nth(2), Some(&5));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_iterator_peekable_last() {
+ let xs = [0, 1, 2, 3, 4, 5];
+ let ys = [0];
+
+ let mut it = xs.iter().peekable();
+ assert_eq!(it.peek(), Some(&&0));
+ assert_eq!(it.last(), Some(&5));
+
+ let mut it = ys.iter().peekable();
+ assert_eq!(it.peek(), Some(&&0));
+ assert_eq!(it.last(), Some(&0));
+
+ let mut it = ys.iter().peekable();
+ assert_eq!(it.next(), Some(&0));
+ assert_eq!(it.peek(), None);
+ assert_eq!(it.last(), None);
+}
+
+/// This is an iterator that follows the Iterator contract,
+/// but it is not fused. After having returned None once, it will start
+/// producing elements if .next() is called again.
+pub struct CycleIter<'a, T: 'a> {
+ index: usize,
+ data: &'a [T],
+}
+
+pub fn cycle<T>(data: &[T]) -> CycleIter<T> {
+ CycleIter {
+ index: 0,
+ data: data,
+ }
+}
+
+impl<'a, T> Iterator for CycleIter<'a, T> {
+ type Item = &'a T;
+ fn next(&mut self) -> Option<Self::Item> {
+ let elt = self.data.get(self.index);
+ self.index += 1;
+ self.index %= 1 + self.data.len();
+ elt
+ }
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_1() {
+ // Check that the loop using .peek() terminates
+ let data = [1, 2, 3];
+ let mut iter = cycle(&data).peekable();
+
+ let mut n = 0;
+ while let Some(_) = iter.next() {
+ let is_the_last = iter.peek().is_none();
+ assert_eq!(is_the_last, n == data.len() - 1);
+ n += 1;
+ if n > data.len() { break; }
+ }
+ assert_eq!(n, data.len());
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_2() {
+ let data = [0];
+ let mut iter = cycle(&data).peekable();
+ iter.next();
+ assert_eq!(iter.peek(), None);
+ assert_eq!(iter.last(), None);
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_3() {
+ let data = [0];
+ let mut iter = cycle(&data).peekable();
+ iter.peek();
+ assert_eq!(iter.nth(0), Some(&0));
+
+ let mut iter = cycle(&data).peekable();
+ iter.next();
+ assert_eq!(iter.peek(), None);
+ assert_eq!(iter.nth(0), None);
+}
+
+#[test]
+fn test_iterator_take_while() {
+ let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+ let ys = [0, 1, 2, 3, 5, 13];
+ let it = xs.iter().take_while(|&x| *x < 15);
+ let mut i = 0;
+ for x in it {
+ assert_eq!(*x, ys[i]);
+ i += 1;
+ }
+ assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_iterator_skip_while() {
+ let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+ let ys = [15, 16, 17, 19];
+ let it = xs.iter().skip_while(|&x| *x < 15);
+ let mut i = 0;
+ for x in it {
+ assert_eq!(*x, ys[i]);
+ i += 1;
+ }
+ assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_iterator_skip() {
+ let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+ let ys = [13, 15, 16, 17, 19, 20, 30];
+ let mut it = xs.iter().skip(5);
+ let mut i = 0;
+ while let Some(&x) = it.next() {
+ assert_eq!(x, ys[i]);
+ i += 1;
+ assert_eq!(it.len(), xs.len()-5-i);
+ }
+ assert_eq!(i, ys.len());
+ assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_skip_doubleended() {
+ let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+ let mut it = xs.iter().rev().skip(5);
+ assert_eq!(it.next(), Some(&15));
+ assert_eq!(it.by_ref().rev().next(), Some(&0));
+ assert_eq!(it.next(), Some(&13));
+ assert_eq!(it.by_ref().rev().next(), Some(&1));
+ assert_eq!(it.next(), Some(&5));
+ assert_eq!(it.by_ref().rev().next(), Some(&2));
+ assert_eq!(it.next(), Some(&3));
+ assert_eq!(it.next(), None);
+ let mut it = xs.iter().rev().skip(5).rev();
+ assert_eq!(it.next(), Some(&0));
+ assert_eq!(it.rev().next(), Some(&15));
+ let mut it_base = xs.iter();
+ {
+ let mut it = it_base.by_ref().skip(5).rev();
+ assert_eq!(it.next(), Some(&30));
+ assert_eq!(it.next(), Some(&20));
+ assert_eq!(it.next(), Some(&19));
+ assert_eq!(it.next(), Some(&17));
+ assert_eq!(it.next(), Some(&16));
+ assert_eq!(it.next(), Some(&15));
+ assert_eq!(it.next(), Some(&13));
+ assert_eq!(it.next(), None);
+ }
+ // make sure the skipped parts have not been consumed
+ assert_eq!(it_base.next(), Some(&0));
+ assert_eq!(it_base.next(), Some(&1));
+ assert_eq!(it_base.next(), Some(&2));
+ assert_eq!(it_base.next(), Some(&3));
+ assert_eq!(it_base.next(), Some(&5));
+ assert_eq!(it_base.next(), None);
+ let it = xs.iter().skip(5).rev();
+ assert_eq!(it.last(), Some(&13));
+}
+
+#[test]
+fn test_iterator_skip_nth() {
+ let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+
+ let mut it = xs.iter().skip(0);
+ assert_eq!(it.nth(0), Some(&0));
+ assert_eq!(it.nth(1), Some(&2));
+
+ let mut it = xs.iter().skip(5);
+ assert_eq!(it.nth(0), Some(&13));
+ assert_eq!(it.nth(1), Some(&16));
+
+ let mut it = xs.iter().skip(12);
+ assert_eq!(it.nth(0), None);
+
+}
+
+#[test]
+fn test_iterator_skip_count() {
+ let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+
+ assert_eq!(xs.iter().skip(0).count(), 12);
+ assert_eq!(xs.iter().skip(1).count(), 11);
+ assert_eq!(xs.iter().skip(11).count(), 1);
+ assert_eq!(xs.iter().skip(12).count(), 0);
+ assert_eq!(xs.iter().skip(13).count(), 0);
+}
+
+#[test]
+fn test_iterator_skip_last() {
+ let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+
+ assert_eq!(xs.iter().skip(0).last(), Some(&30));
+ assert_eq!(xs.iter().skip(1).last(), Some(&30));
+ assert_eq!(xs.iter().skip(11).last(), Some(&30));
+ assert_eq!(xs.iter().skip(12).last(), None);
+ assert_eq!(xs.iter().skip(13).last(), None);
+
+ let mut it = xs.iter().skip(5);
+ assert_eq!(it.next(), Some(&13));
+ assert_eq!(it.last(), Some(&30));
+}
+
+#[test]
+fn test_iterator_take() {
+ let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+ let ys = [0, 1, 2, 3, 5];
+ let mut it = xs.iter().take(5);
+ let mut i = 0;
+ assert_eq!(it.len(), 5);
+ while let Some(&x) = it.next() {
+ assert_eq!(x, ys[i]);
+ i += 1;
+ assert_eq!(it.len(), 5-i);
+ }
+ assert_eq!(i, ys.len());
+ assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_take_nth() {
+ let xs = [0, 1, 2, 4, 5];
+ let mut it = xs.iter();
+ {
+ let mut take = it.by_ref().take(3);
+ let mut i = 0;
+ while let Some(&x) = take.nth(0) {
+ assert_eq!(x, i);
+ i += 1;
+ }
+ }
+ assert_eq!(it.nth(1), Some(&5));
+ assert_eq!(it.nth(0), None);
+
+ let xs = [0, 1, 2, 3, 4];
+ let mut it = xs.iter().take(7);
+ let mut i = 1;
+ while let Some(&x) = it.nth(1) {
+ assert_eq!(x, i);
+ i += 2;
+ }
+}
+
+#[test]
+fn test_iterator_take_short() {
+ let xs = [0, 1, 2, 3];
+ let ys = [0, 1, 2, 3];
+ let mut it = xs.iter().take(5);
+ let mut i = 0;
+ assert_eq!(it.len(), 4);
+ while let Some(&x) = it.next() {
+ assert_eq!(x, ys[i]);
+ i += 1;
+ assert_eq!(it.len(), 4-i);
+ }
+ assert_eq!(i, ys.len());
+ assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_scan() {
+ // test the type inference
+ fn add(old: &mut isize, new: &usize) -> Option<f64> {
+ *old += *new as isize;
+ Some(*old as f64)
+ }
+ let xs = [0, 1, 2, 3, 4];
+ let ys = [0f64, 1.0, 3.0, 6.0, 10.0];
+
+ let it = xs.iter().scan(0, add);
+ let mut i = 0;
+ for x in it {
+ assert_eq!(x, ys[i]);
+ i += 1;
+ }
+ assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_iterator_flat_map() {
+ let xs = [0, 3, 6];
+ let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8];
+ let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3));
+ let mut i = 0;
+ for x in it {
+ assert_eq!(x, ys[i]);
+ i += 1;
+ }
+ assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_inspect() {
+ let xs = [1, 2, 3, 4];
+ let mut n = 0;
+
+ let ys = xs.iter()
+ .cloned()
+ .inspect(|_| n += 1)
+ .collect::<Vec<usize>>();
+
+ assert_eq!(n, xs.len());
+ assert_eq!(&xs[..], &ys[..]);
+}
+
+#[test]
+fn test_cycle() {
+ let cycle_len = 3;
+ let it = (0..).step_by(1).take(cycle_len).cycle();
+ assert_eq!(it.size_hint(), (usize::MAX, None));
+ for (i, x) in it.take(100).enumerate() {
+ assert_eq!(i % cycle_len, x);
+ }
+
+ let mut it = (0..).step_by(1).take(0).cycle();
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_iterator_nth() {
+ let v: &[_] = &[0, 1, 2, 3, 4];
+ for i in 0..v.len() {
+ assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
+ }
+ assert_eq!(v.iter().nth(v.len()), None);
+}
+
+#[test]
+fn test_iterator_last() {
+ let v: &[_] = &[0, 1, 2, 3, 4];
+ assert_eq!(v.iter().last().unwrap(), &4);
+ assert_eq!(v[..1].iter().last().unwrap(), &0);
+}
+
+#[test]
+fn test_iterator_len() {
+ let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+ assert_eq!(v[..4].iter().count(), 4);
+ assert_eq!(v[..10].iter().count(), 10);
+ assert_eq!(v[..0].iter().count(), 0);
+}
+
+#[test]
+fn test_iterator_sum() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+ assert_eq!(v[..4].iter().cloned().sum::<i32>(), 6);
+ assert_eq!(v.iter().cloned().sum::<i32>(), 55);
+ assert_eq!(v[..0].iter().cloned().sum::<i32>(), 0);
+}
+
+#[test]
+fn test_iterator_sum_result() {
+ let v: &[Result<i32, ()>] = &[Ok(1), Ok(2), Ok(3), Ok(4)];
+ assert_eq!(v.iter().cloned().sum::<Result<i32, _>>(), Ok(10));
+ let v: &[Result<i32, ()>] = &[Ok(1), Err(()), Ok(3), Ok(4)];
+ assert_eq!(v.iter().cloned().sum::<Result<i32, _>>(), Err(()));
+}
+
+#[test]
+fn test_iterator_product() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+ assert_eq!(v[..4].iter().cloned().product::<i32>(), 0);
+ assert_eq!(v[1..5].iter().cloned().product::<i32>(), 24);
+ assert_eq!(v[..0].iter().cloned().product::<i32>(), 1);
+}
+
+#[test]
+fn test_iterator_product_result() {
+ let v: &[Result<i32, ()>] = &[Ok(1), Ok(2), Ok(3), Ok(4)];
+ assert_eq!(v.iter().cloned().product::<Result<i32, _>>(), Ok(24));
+ let v: &[Result<i32, ()>] = &[Ok(1), Err(()), Ok(3), Ok(4)];
+ assert_eq!(v.iter().cloned().product::<Result<i32, _>>(), Err(()));
+}
+
+#[test]
+fn test_iterator_max() {
+ let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+ assert_eq!(v[..4].iter().cloned().max(), Some(3));
+ assert_eq!(v.iter().cloned().max(), Some(10));
+ assert_eq!(v[..0].iter().cloned().max(), None);
+}
+
+#[test]
+fn test_iterator_min() {
+ let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+ assert_eq!(v[..4].iter().cloned().min(), Some(0));
+ assert_eq!(v.iter().cloned().min(), Some(0));
+ assert_eq!(v[..0].iter().cloned().min(), None);
+}
+
+#[test]
+fn test_iterator_size_hint() {
+ let c = (0..).step_by(1);
+ let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let v2 = &[10, 11, 12];
+ let vi = v.iter();
+
+ assert_eq!(c.size_hint(), (usize::MAX, None));
+ assert_eq!(vi.clone().size_hint(), (10, Some(10)));
+
+ assert_eq!(c.clone().take(5).size_hint(), (5, Some(5)));
+ assert_eq!(c.clone().skip(5).size_hint().1, None);
+ assert_eq!(c.clone().take_while(|_| false).size_hint(), (0, None));
+ assert_eq!(c.clone().skip_while(|_| false).size_hint(), (0, None));
+ assert_eq!(c.clone().enumerate().size_hint(), (usize::MAX, None));
+ assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (usize::MAX, None));
+ assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10)));
+ assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None));
+ assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None));
+ assert_eq!(c.clone().map(|_| 0).size_hint(), (usize::MAX, None));
+ assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None));
+
+ assert_eq!(vi.clone().take(5).size_hint(), (5, Some(5)));
+ assert_eq!(vi.clone().take(12).size_hint(), (10, Some(10)));
+ assert_eq!(vi.clone().skip(3).size_hint(), (7, Some(7)));
+ assert_eq!(vi.clone().skip(12).size_hint(), (0, Some(0)));
+ assert_eq!(vi.clone().take_while(|_| false).size_hint(), (0, Some(10)));
+ assert_eq!(vi.clone().skip_while(|_| false).size_hint(), (0, Some(10)));
+ assert_eq!(vi.clone().enumerate().size_hint(), (10, Some(10)));
+ assert_eq!(vi.clone().chain(v2).size_hint(), (13, Some(13)));
+ assert_eq!(vi.clone().zip(v2).size_hint(), (3, Some(3)));
+ assert_eq!(vi.clone().scan(0, |_,_| Some(0)).size_hint(), (0, Some(10)));
+ assert_eq!(vi.clone().filter(|_| false).size_hint(), (0, Some(10)));
+ assert_eq!(vi.clone().map(|&i| i+1).size_hint(), (10, Some(10)));
+ assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10)));
+}
+
+#[test]
+fn test_collect() {
+ let a = vec![1, 2, 3, 4, 5];
+ let b: Vec<isize> = a.iter().cloned().collect();
+ assert!(a == b);
+}
+
+#[test]
+fn test_all() {
+ let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
+ assert!(v.iter().all(|&x| x < 10));
+ assert!(!v.iter().all(|&x| x % 2 == 0));
+ assert!(!v.iter().all(|&x| x > 100));
+ assert!(v[..0].iter().all(|_| panic!()));
+}
+
+#[test]
+fn test_any() {
+ let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
+ assert!(v.iter().any(|&x| x < 10));
+ assert!(v.iter().any(|&x| x % 2 == 0));
+ assert!(!v.iter().any(|&x| x > 100));
+ assert!(!v[..0].iter().any(|_| panic!()));
+}
+
+#[test]
+fn test_find() {
+ let v: &[isize] = &[1, 3, 9, 27, 103, 14, 11];
+ assert_eq!(*v.iter().find(|&&x| x & 1 == 0).unwrap(), 14);
+ assert_eq!(*v.iter().find(|&&x| x % 3 == 0).unwrap(), 3);
+ assert!(v.iter().find(|&&x| x % 12 == 0).is_none());
+}
+
+#[test]
+fn test_position() {
+ let v = &[1, 3, 9, 27, 103, 14, 11];
+ assert_eq!(v.iter().position(|x| *x & 1 == 0).unwrap(), 5);
+ assert_eq!(v.iter().position(|x| *x % 3 == 0).unwrap(), 1);
+ assert!(v.iter().position(|x| *x % 12 == 0).is_none());
+}
+
+#[test]
+fn test_count() {
+ let xs = &[1, 2, 2, 1, 5, 9, 0, 2];
+ assert_eq!(xs.iter().filter(|x| **x == 2).count(), 3);
+ assert_eq!(xs.iter().filter(|x| **x == 5).count(), 1);
+ assert_eq!(xs.iter().filter(|x| **x == 95).count(), 0);
+}
+
+#[test]
+fn test_max_by_key() {
+ let xs: &[isize] = &[-3, 0, 1, 5, -10];
+ assert_eq!(*xs.iter().max_by_key(|x| x.abs()).unwrap(), -10);
+}
+
+#[test]
+fn test_max_by() {
+ let xs: &[isize] = &[-3, 0, 1, 5, -10];
+ assert_eq!(*xs.iter().max_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), -10);
+}
+
+#[test]
+fn test_min_by_key() {
+ let xs: &[isize] = &[-3, 0, 1, 5, -10];
+ assert_eq!(*xs.iter().min_by_key(|x| x.abs()).unwrap(), 0);
+}
+
+#[test]
+fn test_min_by() {
+ let xs: &[isize] = &[-3, 0, 1, 5, -10];
+ assert_eq!(*xs.iter().min_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), 0);
+}
+
+#[test]
+fn test_by_ref() {
+ let mut xs = 0..10;
+ // sum the first five values
+ let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b);
+ assert_eq!(partial_sum, 10);
+ assert_eq!(xs.next(), Some(5));
+}
+
+#[test]
+fn test_rev() {
+ let xs = [2, 4, 6, 8, 10, 12, 14, 16];
+ let mut it = xs.iter();
+ it.next();
+ it.next();
+ assert!(it.rev().cloned().collect::<Vec<isize>>() ==
+ vec![16, 14, 12, 10, 8, 6]);
+}
+
+#[test]
+fn test_cloned() {
+ let xs = [2, 4, 6, 8];
+
+ let mut it = xs.iter().cloned();
+ assert_eq!(it.len(), 4);
+ assert_eq!(it.next(), Some(2));
+ assert_eq!(it.len(), 3);
+ assert_eq!(it.next(), Some(4));
+ assert_eq!(it.len(), 2);
+ assert_eq!(it.next_back(), Some(8));
+ assert_eq!(it.len(), 1);
+ assert_eq!(it.next_back(), Some(6));
+ assert_eq!(it.len(), 0);
+ assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_map() {
+ let xs = [1, 2, 3, 4, 5, 6];
+ let mut it = xs.iter().map(|&x| x * -1);
+ assert_eq!(it.next(), Some(-1));
+ assert_eq!(it.next(), Some(-2));
+ assert_eq!(it.next_back(), Some(-6));
+ assert_eq!(it.next_back(), Some(-5));
+ assert_eq!(it.next(), Some(-3));
+ assert_eq!(it.next_back(), Some(-4));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_double_ended_enumerate() {
+ let xs = [1, 2, 3, 4, 5, 6];
+ let mut it = xs.iter().cloned().enumerate();
+ assert_eq!(it.next(), Some((0, 1)));
+ assert_eq!(it.next(), Some((1, 2)));
+ assert_eq!(it.next_back(), Some((5, 6)));
+ assert_eq!(it.next_back(), Some((4, 5)));
+ assert_eq!(it.next_back(), Some((3, 4)));
+ assert_eq!(it.next_back(), Some((2, 3)));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_double_ended_zip() {
+ let xs = [1, 2, 3, 4, 5, 6];
+ let ys = [1, 2, 3, 7];
+ let a = xs.iter().cloned();
+ let b = ys.iter().cloned();
+ let mut it = a.zip(b);
+ assert_eq!(it.next(), Some((1, 1)));
+ assert_eq!(it.next(), Some((2, 2)));
+ assert_eq!(it.next_back(), Some((4, 7)));
+ assert_eq!(it.next_back(), Some((3, 3)));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_double_ended_filter() {
+ let xs = [1, 2, 3, 4, 5, 6];
+ let mut it = xs.iter().filter(|&x| *x & 1 == 0);
+ assert_eq!(it.next_back().unwrap(), &6);
+ assert_eq!(it.next_back().unwrap(), &4);
+ assert_eq!(it.next().unwrap(), &2);
+ assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_filter_map() {
+ let xs = [1, 2, 3, 4, 5, 6];
+ let mut it = xs.iter().filter_map(|&x| if x & 1 == 0 { Some(x * 2) } else { None });
+ assert_eq!(it.next_back().unwrap(), 12);
+ assert_eq!(it.next_back().unwrap(), 8);
+ assert_eq!(it.next().unwrap(), 4);
+ assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_chain() {
+ let xs = [1, 2, 3, 4, 5];
+ let ys = [7, 9, 11];
+ let mut it = xs.iter().chain(&ys).rev();
+ assert_eq!(it.next().unwrap(), &11);
+ assert_eq!(it.next().unwrap(), &9);
+ assert_eq!(it.next_back().unwrap(), &1);
+ assert_eq!(it.next_back().unwrap(), &2);
+ assert_eq!(it.next_back().unwrap(), &3);
+ assert_eq!(it.next_back().unwrap(), &4);
+ assert_eq!(it.next_back().unwrap(), &5);
+ assert_eq!(it.next_back().unwrap(), &7);
+ assert_eq!(it.next_back(), None);
+
+
+ // test that .chain() is well behaved with an unfused iterator
+ struct CrazyIterator(bool);
+ impl CrazyIterator { fn new() -> CrazyIterator { CrazyIterator(false) } }
+ impl Iterator for CrazyIterator {
+ type Item = i32;
+ fn next(&mut self) -> Option<i32> {
+ if self.0 { Some(99) } else { self.0 = true; None }
+ }
+ }
+
+ impl DoubleEndedIterator for CrazyIterator {
+ fn next_back(&mut self) -> Option<i32> {
+ self.next()
+ }
+ }
+
+ assert_eq!(CrazyIterator::new().chain(0..10).rev().last(), Some(0));
+ assert!((0..10).chain(CrazyIterator::new()).rev().any(|i| i == 0));
+}
+
+#[test]
+fn test_rposition() {
+ fn f(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'b' }
+ fn g(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'd' }
+ let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+
+ assert_eq!(v.iter().rposition(f), Some(3));
+ assert!(v.iter().rposition(g).is_none());
+}
+
+#[test]
+#[should_panic]
+fn test_rposition_panic() {
+ let v: [(Box<_>, Box<_>); 4] =
+ [(box 0, box 0), (box 0, box 0),
+ (box 0, box 0), (box 0, box 0)];
+ let mut i = 0;
+ v.iter().rposition(|_elt| {
+ if i == 2 {
+ panic!()
+ }
+ i += 1;
+ false
+ });
+}
+
+
+#[test]
+fn test_double_ended_flat_map() {
+ let u = [0,1];
+ let v = [5,6,7,8];
+ let mut it = u.iter().flat_map(|x| &v[*x..v.len()]);
+ assert_eq!(it.next_back().unwrap(), &8);
+ assert_eq!(it.next().unwrap(), &5);
+ assert_eq!(it.next_back().unwrap(), &7);
+ assert_eq!(it.next_back().unwrap(), &6);
+ assert_eq!(it.next_back().unwrap(), &8);
+ assert_eq!(it.next().unwrap(), &6);
+ assert_eq!(it.next_back().unwrap(), &7);
+ assert_eq!(it.next_back(), None);
+ assert_eq!(it.next(), None);
+ assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_range() {
+ assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
+ for _ in (10..0).rev() {
+ panic!("unreachable");
+ }
+
+ assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
+ for _ in (10..0).rev() {
+ panic!("unreachable");
+ }
+}
+
+#[test]
+fn test_range() {
+ assert_eq!((0..5).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
+ assert_eq!((-10..-1).collect::<Vec<_>>(), [-10, -9, -8, -7, -6, -5, -4, -3, -2]);
+ assert_eq!((0..5).rev().collect::<Vec<_>>(), [4, 3, 2, 1, 0]);
+ assert_eq!((200..-5).count(), 0);
+ assert_eq!((200..-5).rev().count(), 0);
+ assert_eq!((200..200).count(), 0);
+ assert_eq!((200..200).rev().count(), 0);
+
+ assert_eq!((0..100).size_hint(), (100, Some(100)));
+ // this test is only meaningful when sizeof usize < sizeof u64
+ assert_eq!((usize::MAX - 1..usize::MAX).size_hint(), (1, Some(1)));
+ assert_eq!((-10..-1).size_hint(), (9, Some(9)));
+ assert_eq!((-1..-10).size_hint(), (0, Some(0)));
+
+ assert_eq!((-70..58).size_hint(), (128, Some(128)));
+ assert_eq!((-128..127).size_hint(), (255, Some(255)));
+ assert_eq!((-2..isize::MAX).size_hint(),
+ (isize::MAX as usize + 2, Some(isize::MAX as usize + 2)));
+}
+
+#[test]
+fn test_range_step() {
+ assert_eq!((0..20).step_by(5).collect::<Vec<isize>>(), [0, 5, 10, 15]);
+ assert_eq!((20..0).step_by(-5).collect::<Vec<isize>>(), [20, 15, 10, 5]);
+ assert_eq!((20..0).step_by(-6).collect::<Vec<isize>>(), [20, 14, 8, 2]);
+ assert_eq!((200..255).step_by(50).collect::<Vec<u8>>(), [200, 250]);
+ assert_eq!((200..-5).step_by(1).collect::<Vec<isize>>(), []);
+ assert_eq!((200..200).step_by(1).collect::<Vec<isize>>(), []);
+
+ assert_eq!((0..20).step_by(1).size_hint(), (20, Some(20)));
+ assert_eq!((0..20).step_by(21).size_hint(), (1, Some(1)));
+ assert_eq!((0..20).step_by(5).size_hint(), (4, Some(4)));
+ assert_eq!((20..0).step_by(-5).size_hint(), (4, Some(4)));
+ assert_eq!((20..0).step_by(-6).size_hint(), (4, Some(4)));
+ assert_eq!((20..-5).step_by(1).size_hint(), (0, Some(0)));
+ assert_eq!((20..20).step_by(1).size_hint(), (0, Some(0)));
+ assert_eq!((0..1).step_by(0).size_hint(), (0, None));
+ assert_eq!((i8::MAX..i8::MIN).step_by(i8::MIN).size_hint(), (2, Some(2)));
+ assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX).size_hint(), (3, Some(3)));
+ assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX)));
+}
+
+#[test]
+fn test_repeat() {
+ let mut it = repeat(42);
+ assert_eq!(it.next(), Some(42));
+ assert_eq!(it.next(), Some(42));
+ assert_eq!(it.next(), Some(42));
+}
+
+#[test]
+fn test_fuse() {
+ let mut it = 0..3;
+ assert_eq!(it.len(), 3);
+ assert_eq!(it.next(), Some(0));
+ assert_eq!(it.len(), 2);
+ assert_eq!(it.next(), Some(1));
+ assert_eq!(it.len(), 1);
+ assert_eq!(it.next(), Some(2));
+ assert_eq!(it.len(), 0);
+ assert_eq!(it.next(), None);
+ assert_eq!(it.len(), 0);
+ assert_eq!(it.next(), None);
+ assert_eq!(it.len(), 0);
+ assert_eq!(it.next(), None);
+ assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_fuse_nth() {
+ let xs = [0, 1, 2];
+ let mut it = xs.iter();
+
+ assert_eq!(it.len(), 3);
+ assert_eq!(it.nth(2), Some(&2));
+ assert_eq!(it.len(), 0);
+ assert_eq!(it.nth(2), None);
+ assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_fuse_last() {
+ let xs = [0, 1, 2];
+ let it = xs.iter();
+
+ assert_eq!(it.len(), 3);
+ assert_eq!(it.last(), Some(&2));
+}
+
+#[test]
+fn test_fuse_count() {
+ let xs = [0, 1, 2];
+ let it = xs.iter();
+
+ assert_eq!(it.len(), 3);
+ assert_eq!(it.count(), 3);
+ // Can't check len now because count consumes.
+}
+
+#[test]
+fn test_once() {
+ let mut it = once(42);
+ assert_eq!(it.next(), Some(42));
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_empty() {
+ let mut it = empty::<i32>();
+ assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_chain_fold() {
+ let xs = [1, 2, 3];
+ let ys = [1, 2, 0];
+
+ let mut iter = xs.iter().chain(&ys);
+ iter.next();
+ let mut result = Vec::new();
+ iter.fold((), |(), &elt| result.push(elt));
+ assert_eq!(&[2, 3, 1, 2, 0], &result[..]);
+}
+
--- /dev/null
+// Copyright 2014 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.
+
+#![deny(warnings)]
+
+#![feature(box_syntax)]
+#![feature(char_escape_debug)]
+#![feature(const_fn)]
+#![feature(core_private_bignum)]
+#![feature(core_private_diy_float)]
+#![feature(dec2flt)]
+#![feature(decode_utf8)]
+#![feature(fixed_size_array)]
+#![feature(flt2dec)]
+#![feature(fmt_internals)]
+#![feature(libc)]
+#![feature(nonzero)]
+#![feature(rand)]
+#![feature(raw)]
+#![feature(sip_hash_13)]
+#![feature(slice_patterns)]
+#![feature(sort_internals)]
+#![feature(sort_unstable)]
+#![feature(step_by)]
+#![feature(test)]
+#![feature(try_from)]
+#![feature(unicode)]
+#![feature(unique)]
+
+extern crate core;
+extern crate test;
+extern crate libc;
+extern crate std_unicode;
+extern crate rand;
+
+mod any;
+mod array;
+mod atomic;
+mod cell;
+mod char;
+mod clone;
+mod cmp;
+mod fmt;
+mod hash;
+mod intrinsics;
+mod iter;
+mod mem;
+mod nonzero;
+mod num;
+mod ops;
+mod option;
+mod ptr;
+mod result;
+mod slice;
+mod str;
+mod tuple;
--- /dev/null
+// Copyright 2014-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.
+
+use core::mem::*;
+
+#[test]
+fn size_of_basic() {
+ assert_eq!(size_of::<u8>(), 1);
+ assert_eq!(size_of::<u16>(), 2);
+ assert_eq!(size_of::<u32>(), 4);
+ assert_eq!(size_of::<u64>(), 8);
+}
+
+#[test]
+#[cfg(target_pointer_width = "16")]
+fn size_of_16() {
+ assert_eq!(size_of::<usize>(), 2);
+ assert_eq!(size_of::<*const usize>(), 2);
+}
+
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn size_of_32() {
+ assert_eq!(size_of::<usize>(), 4);
+ assert_eq!(size_of::<*const usize>(), 4);
+}
+
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn size_of_64() {
+ assert_eq!(size_of::<usize>(), 8);
+ assert_eq!(size_of::<*const usize>(), 8);
+}
+
+#[test]
+fn size_of_val_basic() {
+ assert_eq!(size_of_val(&1u8), 1);
+ assert_eq!(size_of_val(&1u16), 2);
+ assert_eq!(size_of_val(&1u32), 4);
+ assert_eq!(size_of_val(&1u64), 8);
+}
+
+#[test]
+fn align_of_basic() {
+ assert_eq!(align_of::<u8>(), 1);
+ assert_eq!(align_of::<u16>(), 2);
+ assert_eq!(align_of::<u32>(), 4);
+}
+
+#[test]
+#[cfg(target_pointer_width = "16")]
+fn align_of_16() {
+ assert_eq!(align_of::<usize>(), 2);
+ assert_eq!(align_of::<*const usize>(), 2);
+}
+
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn align_of_32() {
+ assert_eq!(align_of::<usize>(), 4);
+ assert_eq!(align_of::<*const usize>(), 4);
+}
+
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn align_of_64() {
+ assert_eq!(align_of::<usize>(), 8);
+ assert_eq!(align_of::<*const usize>(), 8);
+}
+
+#[test]
+fn align_of_val_basic() {
+ assert_eq!(align_of_val(&1u8), 1);
+ assert_eq!(align_of_val(&1u16), 2);
+ assert_eq!(align_of_val(&1u32), 4);
+}
+
+#[test]
+fn test_swap() {
+ let mut x = 31337;
+ let mut y = 42;
+ swap(&mut x, &mut y);
+ assert_eq!(x, 42);
+ assert_eq!(y, 31337);
+}
+
+#[test]
+fn test_replace() {
+ let mut x = Some("test".to_string());
+ let y = replace(&mut x, None);
+ assert!(x.is_none());
+ assert!(y.is_some());
+}
+
+#[test]
+fn test_transmute_copy() {
+ assert_eq!(1, unsafe { transmute_copy(&1) });
+}
+
+#[test]
+fn test_transmute() {
+ trait Foo { fn dummy(&self) { } }
+ impl Foo for isize {}
+
+ let a = box 100isize as Box<Foo>;
+ unsafe {
+ let x: ::core::raw::TraitObject = transmute(a);
+ assert!(*(x.data as *const isize) == 100);
+ let _x: Box<Foo> = transmute(x);
+ }
+
+ unsafe {
+ assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
+ }
+}
+
--- /dev/null
+// Copyright 2012-2014 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.
+
+use core::nonzero::NonZero;
+use core::option::Option;
+use core::option::Option::{Some, None};
+use std::mem::size_of;
+
+#[test]
+fn test_create_nonzero_instance() {
+ let _a = unsafe {
+ NonZero::new(21)
+ };
+}
+
+#[test]
+fn test_size_nonzero_in_option() {
+ assert_eq!(size_of::<NonZero<u32>>(), size_of::<Option<NonZero<u32>>>());
+}
+
+#[test]
+fn test_match_on_nonzero_option() {
+ let a = Some(unsafe {
+ NonZero::new(42)
+ });
+ match a {
+ Some(val) => assert_eq!(*val, 42),
+ None => panic!("unexpected None while matching on Some(NonZero(_))")
+ }
+
+ match unsafe { Some(NonZero::new(43)) } {
+ Some(val) => assert_eq!(*val, 43),
+ None => panic!("unexpected None while matching on Some(NonZero(_))")
+ }
+}
+
+#[test]
+fn test_match_option_empty_vec() {
+ let a: Option<Vec<isize>> = Some(vec![]);
+ match a {
+ None => panic!("unexpected None while matching on Some(vec![])"),
+ _ => {}
+ }
+}
+
+#[test]
+fn test_match_option_vec() {
+ let a = Some(vec![1, 2, 3, 4]);
+ match a {
+ Some(v) => assert_eq!(v, [1, 2, 3, 4]),
+ None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])")
+ }
+}
+
+#[test]
+fn test_match_option_rc() {
+ use std::rc::Rc;
+
+ let five = Rc::new(5);
+ match Some(five) {
+ Some(r) => assert_eq!(*r, 5),
+ None => panic!("unexpected None while matching on Some(Rc::new(5))")
+ }
+}
+
+#[test]
+fn test_match_option_arc() {
+ use std::sync::Arc;
+
+ let five = Arc::new(5);
+ match Some(five) {
+ Some(a) => assert_eq!(*a, 5),
+ None => panic!("unexpected None while matching on Some(Arc::new(5))")
+ }
+}
+
+#[test]
+fn test_match_option_empty_string() {
+ let a = Some(String::new());
+ match a {
+ None => panic!("unexpected None while matching on Some(String::new())"),
+ _ => {}
+ }
+}
+
+#[test]
+fn test_match_option_string() {
+ let five = "Five".to_string();
+ match Some(five) {
+ Some(s) => assert_eq!(s, "Five"),
+ None => panic!("unexpected None while matching on Some(String { ... })")
+ }
+}
--- /dev/null
+// Copyright 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.
+
+use std::prelude::v1::*;
+use core::num::bignum::tests::Big8x3 as Big;
+
+#[test]
+#[should_panic]
+fn test_from_u64_overflow() {
+ Big::from_u64(0x1000000);
+}
+
+#[test]
+fn test_add() {
+ assert_eq!(*Big::from_small(3).add(&Big::from_small(4)), Big::from_small(7));
+ assert_eq!(*Big::from_small(3).add(&Big::from_small(0)), Big::from_small(3));
+ assert_eq!(*Big::from_small(0).add(&Big::from_small(3)), Big::from_small(3));
+ assert_eq!(*Big::from_small(3).add(&Big::from_u64(0xfffe)), Big::from_u64(0x10001));
+ assert_eq!(*Big::from_u64(0xfedc).add(&Big::from_u64(0x789)), Big::from_u64(0x10665));
+ assert_eq!(*Big::from_u64(0x789).add(&Big::from_u64(0xfedc)), Big::from_u64(0x10665));
+}
+
+#[test]
+#[should_panic]
+fn test_add_overflow_1() {
+ Big::from_small(1).add(&Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_add_overflow_2() {
+ Big::from_u64(0xffffff).add(&Big::from_small(1));
+}
+
+#[test]
+fn test_add_small() {
+ assert_eq!(*Big::from_small(3).add_small(4), Big::from_small(7));
+ assert_eq!(*Big::from_small(3).add_small(0), Big::from_small(3));
+ assert_eq!(*Big::from_small(0).add_small(3), Big::from_small(3));
+ assert_eq!(*Big::from_small(7).add_small(250), Big::from_u64(257));
+ assert_eq!(*Big::from_u64(0x7fff).add_small(1), Big::from_u64(0x8000));
+ assert_eq!(*Big::from_u64(0x2ffe).add_small(0x35), Big::from_u64(0x3033));
+ assert_eq!(*Big::from_small(0xdc).add_small(0x89), Big::from_u64(0x165));
+}
+
+#[test]
+#[should_panic]
+fn test_add_small_overflow() {
+ Big::from_u64(0xffffff).add_small(1);
+}
+
+#[test]
+fn test_sub() {
+ assert_eq!(*Big::from_small(7).sub(&Big::from_small(4)), Big::from_small(3));
+ assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x789)), Big::from_u64(0xfedc));
+ assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0xfedc)), Big::from_u64(0x789));
+ assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10664)), Big::from_small(1));
+ assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10665)), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_sub_underflow_1() {
+ Big::from_u64(0x10665).sub(&Big::from_u64(0x10666));
+}
+
+#[test]
+#[should_panic]
+fn test_sub_underflow_2() {
+ Big::from_small(0).sub(&Big::from_u64(0x123456));
+}
+
+#[test]
+fn test_mul_small() {
+ assert_eq!(*Big::from_small(7).mul_small(5), Big::from_small(35));
+ assert_eq!(*Big::from_small(0xff).mul_small(0xff), Big::from_u64(0xfe01));
+ assert_eq!(*Big::from_u64(0xffffff/13).mul_small(13), Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_small_overflow() {
+ Big::from_u64(0x800000).mul_small(2);
+}
+
+#[test]
+fn test_mul_pow2() {
+ assert_eq!(*Big::from_small(0x7).mul_pow2(4), Big::from_small(0x70));
+ assert_eq!(*Big::from_small(0xff).mul_pow2(1), Big::from_u64(0x1fe));
+ assert_eq!(*Big::from_small(0xff).mul_pow2(12), Big::from_u64(0xff000));
+ assert_eq!(*Big::from_small(0x1).mul_pow2(23), Big::from_u64(0x800000));
+ assert_eq!(*Big::from_u64(0x123).mul_pow2(0), Big::from_u64(0x123));
+ assert_eq!(*Big::from_u64(0x123).mul_pow2(7), Big::from_u64(0x9180));
+ assert_eq!(*Big::from_u64(0x123).mul_pow2(15), Big::from_u64(0x918000));
+ assert_eq!(*Big::from_small(0).mul_pow2(23), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow2_overflow_1() {
+ Big::from_u64(0x1).mul_pow2(24);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow2_overflow_2() {
+ Big::from_u64(0x123).mul_pow2(16);
+}
+
+#[test]
+fn test_mul_pow5() {
+ assert_eq!(*Big::from_small(42).mul_pow5(0), Big::from_small(42));
+ assert_eq!(*Big::from_small(1).mul_pow5(2), Big::from_small(25));
+ assert_eq!(*Big::from_small(1).mul_pow5(4), Big::from_u64(25 * 25));
+ assert_eq!(*Big::from_small(4).mul_pow5(3), Big::from_u64(500));
+ assert_eq!(*Big::from_small(140).mul_pow5(2), Big::from_u64(25 * 140));
+ assert_eq!(*Big::from_small(25).mul_pow5(1), Big::from_small(125));
+ assert_eq!(*Big::from_small(125).mul_pow5(7), Big::from_u64(9765625));
+ assert_eq!(*Big::from_small(0).mul_pow5(127), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow5_overflow_1() {
+ Big::from_small(1).mul_pow5(12);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow5_overflow_2() {
+ Big::from_small(230).mul_pow5(8);
+}
+
+#[test]
+fn test_mul_digits() {
+ assert_eq!(*Big::from_small(3).mul_digits(&[5]), Big::from_small(15));
+ assert_eq!(*Big::from_small(0xff).mul_digits(&[0xff]), Big::from_u64(0xfe01));
+ assert_eq!(*Big::from_u64(0x123).mul_digits(&[0x56, 0x4]), Big::from_u64(0x4edc2));
+ assert_eq!(*Big::from_u64(0x12345).mul_digits(&[0x67]), Big::from_u64(0x7530c3));
+ assert_eq!(*Big::from_small(0x12).mul_digits(&[0x67, 0x45, 0x3]), Big::from_u64(0x3ae13e));
+ assert_eq!(*Big::from_u64(0xffffff/13).mul_digits(&[13]), Big::from_u64(0xffffff));
+ assert_eq!(*Big::from_small(13).mul_digits(&[0x3b, 0xb1, 0x13]), Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_digits_overflow_1() {
+ Big::from_u64(0x800000).mul_digits(&[2]);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_digits_overflow_2() {
+ Big::from_u64(0x1000).mul_digits(&[0, 0x10]);
+}
+
+#[test]
+fn test_div_rem_small() {
+ let as_val = |(q, r): (&mut Big, u8)| (q.clone(), r);
+ assert_eq!(as_val(Big::from_small(0xff).div_rem_small(15)), (Big::from_small(17), 0));
+ assert_eq!(as_val(Big::from_small(0xff).div_rem_small(16)), (Big::from_small(15), 15));
+ assert_eq!(as_val(Big::from_small(3).div_rem_small(40)), (Big::from_small(0), 3));
+ assert_eq!(as_val(Big::from_u64(0xffffff).div_rem_small(123)),
+ (Big::from_u64(0xffffff / 123), (0xffffffu64 % 123) as u8));
+ assert_eq!(as_val(Big::from_u64(0x10000).div_rem_small(123)),
+ (Big::from_u64(0x10000 / 123), (0x10000u64 % 123) as u8));
+}
+
+#[test]
+fn test_div_rem() {
+ fn div_rem(n: u64, d: u64) -> (Big, Big) {
+ let mut q = Big::from_small(42);
+ let mut r = Big::from_small(42);
+ Big::from_u64(n).div_rem(&Big::from_u64(d), &mut q, &mut r);
+ (q, r)
+ }
+ assert_eq!(div_rem(1, 1), (Big::from_small(1), Big::from_small(0)));
+ assert_eq!(div_rem(4, 3), (Big::from_small(1), Big::from_small(1)));
+ assert_eq!(div_rem(1, 7), (Big::from_small(0), Big::from_small(1)));
+ assert_eq!(div_rem(45, 9), (Big::from_small(5), Big::from_small(0)));
+ assert_eq!(div_rem(103, 9), (Big::from_small(11), Big::from_small(4)));
+ assert_eq!(div_rem(123456, 77), (Big::from_u64(1603), Big::from_small(25)));
+ assert_eq!(div_rem(0xffff, 1), (Big::from_u64(0xffff), Big::from_small(0)));
+ assert_eq!(div_rem(0xeeee, 0xffff), (Big::from_small(0), Big::from_u64(0xeeee)));
+ assert_eq!(div_rem(2_000_000, 2), (Big::from_u64(1_000_000), Big::from_u64(0)));
+}
+
+#[test]
+fn test_is_zero() {
+ assert!(Big::from_small(0).is_zero());
+ assert!(!Big::from_small(3).is_zero());
+ assert!(!Big::from_u64(0x123).is_zero());
+ assert!(!Big::from_u64(0xffffff).sub(&Big::from_u64(0xfffffe)).is_zero());
+ assert!(Big::from_u64(0xffffff).sub(&Big::from_u64(0xffffff)).is_zero());
+}
+
+#[test]
+fn test_get_bit() {
+ let x = Big::from_small(0b1101);
+ assert_eq!(x.get_bit(0), 1);
+ assert_eq!(x.get_bit(1), 0);
+ assert_eq!(x.get_bit(2), 1);
+ assert_eq!(x.get_bit(3), 1);
+ let y = Big::from_u64(1 << 15);
+ assert_eq!(y.get_bit(14), 0);
+ assert_eq!(y.get_bit(15), 1);
+ assert_eq!(y.get_bit(16), 0);
+}
+
+#[test]
+#[should_panic]
+fn test_get_bit_out_of_range() {
+ Big::from_small(42).get_bit(24);
+}
+
+#[test]
+fn test_bit_length() {
+ assert_eq!(Big::from_small(0).bit_length(), 0);
+ assert_eq!(Big::from_small(1).bit_length(), 1);
+ assert_eq!(Big::from_small(5).bit_length(), 3);
+ assert_eq!(Big::from_small(0x18).bit_length(), 5);
+ assert_eq!(Big::from_u64(0x4073).bit_length(), 15);
+ assert_eq!(Big::from_u64(0xffffff).bit_length(), 24);
+}
+
+#[test]
+fn test_ord() {
+ assert!(Big::from_u64(0) < Big::from_u64(0xffffff));
+ assert!(Big::from_u64(0x102) < Big::from_u64(0x201));
+}
+
+#[test]
+fn test_fmt() {
+ assert_eq!(format!("{:?}", Big::from_u64(0)), "0x0");
+ assert_eq!(format!("{:?}", Big::from_u64(0x1)), "0x1");
+ assert_eq!(format!("{:?}", Big::from_u64(0x12)), "0x12");
+ assert_eq!(format!("{:?}", Big::from_u64(0x123)), "0x1_23");
+ assert_eq!(format!("{:?}", Big::from_u64(0x1234)), "0x12_34");
+ assert_eq!(format!("{:?}", Big::from_u64(0x12345)), "0x1_23_45");
+ assert_eq!(format!("{:?}", Big::from_u64(0x123456)), "0x12_34_56");
+}
+
--- /dev/null
+// Copyright 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.
+
+#![allow(overflowing_literals)]
+
+use std::{i64, f32, f64};
+
+mod parse;
+mod rawfp;
+
+// Take a float literal, turn it into a string in various ways (that are all trusted
+// to be correct) and see if those strings are parsed back to the value of the literal.
+// Requires a *polymorphic literal*, i.e. one that can serve as f64 as well as f32.
+macro_rules! test_literal {
+ ($x: expr) => ({
+ let x32: f32 = $x;
+ let x64: f64 = $x;
+ let inputs = &[stringify!($x).into(), format!("{:?}", x64), format!("{:e}", x64)];
+ for input in inputs {
+ assert_eq!(input.parse(), Ok(x64));
+ assert_eq!(input.parse(), Ok(x32));
+ let neg_input = &format!("-{}", input);
+ assert_eq!(neg_input.parse(), Ok(-x64));
+ assert_eq!(neg_input.parse(), Ok(-x32));
+ }
+ })
+}
+
+#[test]
+fn ordinary() {
+ test_literal!(1.0);
+ test_literal!(3e-5);
+ test_literal!(0.1);
+ test_literal!(12345.);
+ test_literal!(0.9999999);
+ test_literal!(2.2250738585072014e-308);
+}
+
+#[test]
+fn special_code_paths() {
+ test_literal!(36893488147419103229.0); // 2^65 - 3, triggers half-to-even with even significand
+ test_literal!(101e-33); // Triggers the tricky underflow case in AlgorithmM (for f32)
+ test_literal!(1e23); // Triggers AlgorithmR
+ test_literal!(2075e23); // Triggers another path through AlgorithmR
+ test_literal!(8713e-23); // ... and yet another.
+}
+
+#[test]
+fn large() {
+ test_literal!(1e300);
+ test_literal!(123456789.34567e250);
+ test_literal!(943794359898089732078308743689303290943794359843568973207830874368930329.);
+}
+
+#[test]
+fn subnormals() {
+ test_literal!(5e-324);
+ test_literal!(91e-324);
+ test_literal!(1e-322);
+ test_literal!(13245643e-320);
+ test_literal!(2.22507385851e-308);
+ test_literal!(2.1e-308);
+ test_literal!(4.9406564584124654e-324);
+}
+
+#[test]
+fn infinity() {
+ test_literal!(1e400);
+ test_literal!(1e309);
+ test_literal!(2e308);
+ test_literal!(1.7976931348624e308);
+}
+
+#[test]
+fn zero() {
+ test_literal!(0.0);
+ test_literal!(1e-325);
+ test_literal!(1e-326);
+ test_literal!(1e-500);
+}
+
+#[test]
+fn fast_path_correct() {
+ // This number triggers the fast path and is handled incorrectly when compiling on
+ // x86 without SSE2 (i.e., using the x87 FPU stack).
+ test_literal!(1.448997445238699);
+}
+
+#[test]
+fn lonely_dot() {
+ assert!(".".parse::<f32>().is_err());
+ assert!(".".parse::<f64>().is_err());
+}
+
+#[test]
+fn lonely_sign() {
+ assert!("+".parse::<f32>().is_err());
+ assert!("-".parse::<f64>().is_err());
+}
+
+#[test]
+fn whitespace() {
+ assert!(" 1.0".parse::<f32>().is_err());
+ assert!("1.0 ".parse::<f64>().is_err());
+}
+
+#[test]
+fn nan() {
+ assert!("NaN".parse::<f32>().unwrap().is_nan());
+ assert!("NaN".parse::<f64>().unwrap().is_nan());
+}
+
+#[test]
+fn inf() {
+ assert_eq!("inf".parse(), Ok(f64::INFINITY));
+ assert_eq!("-inf".parse(), Ok(f64::NEG_INFINITY));
+ assert_eq!("inf".parse(), Ok(f32::INFINITY));
+ assert_eq!("-inf".parse(), Ok(f32::NEG_INFINITY));
+}
+
+#[test]
+fn massive_exponent() {
+ let max = i64::MAX;
+ assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
+ assert_eq!(format!("1e-{}000", max).parse(), Ok(0.0));
+ assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
+}
+
+#[test]
+fn borderline_overflow() {
+ let mut s = "0.".to_string();
+ for _ in 0..375 {
+ s.push('3');
+ }
+ // At the time of this writing, this returns Err(..), but this is a bug that should be fixed.
+ // It makes no sense to enshrine that in a test, the important part is that it doesn't panic.
+ let _ = s.parse::<f64>();
+}
--- /dev/null
+// Copyright 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.
+
+use std::iter;
+use core::num::dec2flt::parse::{Decimal, parse_decimal};
+use core::num::dec2flt::parse::ParseResult::{Valid, Invalid};
+
+#[test]
+fn missing_pieces() {
+ let permutations = &[".e", "1e", "e4", "e", ".12e", "321.e", "32.12e+", "12.32e-"];
+ for &s in permutations {
+ assert_eq!(parse_decimal(s), Invalid);
+ }
+}
+
+#[test]
+fn invalid_chars() {
+ let invalid = "r,?<j";
+ let valid_strings = &["123", "666.", ".1", "5e1", "7e-3", "0.0e+1"];
+ for c in invalid.chars() {
+ for s in valid_strings {
+ for i in 0..s.len() {
+ let mut input = String::new();
+ input.push_str(s);
+ input.insert(i, c);
+ assert!(parse_decimal(&input) == Invalid, "did not reject invalid {:?}", input);
+ }
+ }
+ }
+}
+
+#[test]
+fn valid() {
+ assert_eq!(parse_decimal("123.456e789"), Valid(Decimal::new(b"123", b"456", 789)));
+ assert_eq!(parse_decimal("123.456e+789"), Valid(Decimal::new(b"123", b"456", 789)));
+ assert_eq!(parse_decimal("123.456e-789"), Valid(Decimal::new(b"123", b"456", -789)));
+ assert_eq!(parse_decimal(".050"), Valid(Decimal::new(b"", b"050", 0)));
+ assert_eq!(parse_decimal("999"), Valid(Decimal::new(b"999", b"", 0)));
+ assert_eq!(parse_decimal("1.e300"), Valid(Decimal::new(b"1", b"", 300)));
+ assert_eq!(parse_decimal(".1e300"), Valid(Decimal::new(b"", b"1", 300)));
+ assert_eq!(parse_decimal("101e-33"), Valid(Decimal::new(b"101", b"", -33)));
+ let zeros: String = iter::repeat('0').take(25).collect();
+ let s = format!("1.5e{}", zeros);
+ assert_eq!(parse_decimal(&s), Valid(Decimal::new(b"1", b"5", 0)));
+}
--- /dev/null
+// Copyright 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.
+
+use std::f64;
+use std::mem;
+use core::num::diy_float::Fp;
+use core::num::dec2flt::rawfp::{fp_to_float, prev_float, next_float, round_normal};
+
+fn integer_decode(f: f64) -> (u64, i16, i8) {
+ let bits: u64 = unsafe { mem::transmute(f) };
+ let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
+ let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
+ let mantissa = if exponent == 0 {
+ (bits & 0xfffffffffffff) << 1
+ } else {
+ (bits & 0xfffffffffffff) | 0x10000000000000
+ };
+ // Exponent bias + mantissa shift
+ exponent -= 1023 + 52;
+ (mantissa, exponent, sign)
+}
+
+#[test]
+fn fp_to_float_half_to_even() {
+ fn is_normalized(sig: u64) -> bool {
+ // intentionally written without {min,max}_sig() as a sanity check
+ sig >> 52 == 1 && sig >> 53 == 0
+ }
+
+ fn conv(sig: u64) -> u64 {
+ // The significands are perfectly in range, so the exponent should not matter
+ let (m1, e1, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 0 }));
+ assert_eq!(e1, 0 + 64 - 53);
+ let (m2, e2, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 55 }));
+ assert_eq!(e2, 55 + 64 - 53);
+ assert_eq!(m2, m1);
+ let (m3, e3, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: -78 }));
+ assert_eq!(e3, -78 + 64 - 53);
+ assert_eq!(m3, m2);
+ m3
+ }
+
+ let odd = 0x1F_EDCB_A012_345F;
+ let even = odd - 1;
+ assert!(is_normalized(odd));
+ assert!(is_normalized(even));
+ assert_eq!(conv(odd << 11), odd);
+ assert_eq!(conv(even << 11), even);
+ assert_eq!(conv(odd << 11 | 1 << 10), odd + 1);
+ assert_eq!(conv(even << 11 | 1 << 10), even);
+ assert_eq!(conv(even << 11 | 1 << 10 | 1), even + 1);
+ assert_eq!(conv(odd << 11 | 1 << 9), odd);
+ assert_eq!(conv(even << 11 | 1 << 9), even);
+ assert_eq!(conv(odd << 11 | 0x7FF), odd + 1);
+ assert_eq!(conv(even << 11 | 0x7FF), even + 1);
+ assert_eq!(conv(odd << 11 | 0x3FF), odd);
+ assert_eq!(conv(even << 11 | 0x3FF), even);
+}
+
+#[test]
+fn integers_to_f64() {
+ assert_eq!(fp_to_float::<f64>(Fp { f: 1, e: 0 }), 1.0);
+ assert_eq!(fp_to_float::<f64>(Fp { f: 42, e: 7 }), (42 << 7) as f64);
+ assert_eq!(fp_to_float::<f64>(Fp { f: 1 << 20, e: 30 }), (1u64 << 50) as f64);
+ assert_eq!(fp_to_float::<f64>(Fp { f: 4, e: -3 }), 0.5);
+}
+
+const SOME_FLOATS: [f64; 9] =
+ [0.1f64, 33.568, 42.1e-5, 777.0e9, 1.1111, 0.347997,
+ 9843579834.35892, 12456.0e-150, 54389573.0e-150];
+
+
+#[test]
+fn human_f64_roundtrip() {
+ for &x in &SOME_FLOATS {
+ let (f, e, _) = integer_decode(x);
+ let fp = Fp { f: f, e: e};
+ assert_eq!(fp_to_float::<f64>(fp), x);
+ }
+}
+
+#[test]
+fn rounding_overflow() {
+ let x = Fp { f: 0xFF_FF_FF_FF_FF_FF_FF_00u64, e: 42 };
+ let rounded = round_normal::<f64>(x);
+ let adjusted_k = x.e + 64 - 53;
+ assert_eq!(rounded.sig, 1 << 52);
+ assert_eq!(rounded.k, adjusted_k + 1);
+}
+
+#[test]
+fn prev_float_monotonic() {
+ let mut x = 1.0;
+ for _ in 0..100 {
+ let x1 = prev_float(x);
+ assert!(x1 < x);
+ assert!(x - x1 < 1e-15);
+ x = x1;
+ }
+}
+
+const MIN_SUBNORMAL: f64 = 5e-324;
+
+#[test]
+fn next_float_zero() {
+ let tiny = next_float(0.0);
+ assert_eq!(tiny, MIN_SUBNORMAL);
+ assert!(tiny != 0.0);
+}
+
+#[test]
+fn next_float_subnormal() {
+ let second = next_float(MIN_SUBNORMAL);
+ // For subnormals, MIN_SUBNORMAL is the ULP
+ assert!(second != MIN_SUBNORMAL);
+ assert!(second > 0.0);
+ assert_eq!(second - MIN_SUBNORMAL, MIN_SUBNORMAL);
+}
+
+#[test]
+fn next_float_inf() {
+ assert_eq!(next_float(f64::MAX), f64::INFINITY);
+ assert_eq!(next_float(f64::INFINITY), f64::INFINITY);
+}
+
+#[test]
+fn next_prev_identity() {
+ for &x in &SOME_FLOATS {
+ assert_eq!(prev_float(next_float(x)), x);
+ assert_eq!(prev_float(prev_float(next_float(next_float(x)))), x);
+ assert_eq!(next_float(prev_float(x)), x);
+ assert_eq!(next_float(next_float(prev_float(prev_float(x)))), x);
+ }
+}
+
+#[test]
+fn next_float_monotonic() {
+ let mut x = 0.49999999999999;
+ assert!(x < 0.5);
+ for _ in 0..200 {
+ let x1 = next_float(x);
+ assert!(x1 > x);
+ assert!(x1 - x < 1e-15, "next_float_monotonic: delta = {:?}", x1 - x);
+ x = x1;
+ }
+ assert!(x > 0.5);
+}
--- /dev/null
+// Copyright 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.
+
+// FIXME https://github.com/kripken/emscripten/issues/4563
+// NB we have to actually not compile this test to avoid
+// an undefined symbol error
+#![cfg(not(target_os = "emscripten"))]
+
+use core::num::flt2dec::estimator::*;
+
+#[test]
+fn test_estimate_scaling_factor() {
+ macro_rules! assert_almost_eq {
+ ($actual:expr, $expected:expr) => ({
+ let actual = $actual;
+ let expected = $expected;
+ println!("{} - {} = {} - {} = {}", stringify!($expected), stringify!($actual),
+ expected, actual, expected - actual);
+ assert!(expected == actual || expected == actual + 1,
+ "expected {}, actual {}", expected, actual);
+ })
+ }
+
+ assert_almost_eq!(estimate_scaling_factor(1, 0), 0);
+ assert_almost_eq!(estimate_scaling_factor(2, 0), 1);
+ assert_almost_eq!(estimate_scaling_factor(10, 0), 1);
+ assert_almost_eq!(estimate_scaling_factor(11, 0), 2);
+ assert_almost_eq!(estimate_scaling_factor(100, 0), 2);
+ assert_almost_eq!(estimate_scaling_factor(101, 0), 3);
+ assert_almost_eq!(estimate_scaling_factor(10000000000000000000, 0), 19);
+ assert_almost_eq!(estimate_scaling_factor(10000000000000000001, 0), 20);
+
+ // 1/2^20 = 0.00000095367...
+ assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000, -20), -6);
+ assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000 + 1, -20), -5);
+ assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000, -20), -5);
+ assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000 + 1, -20), -4);
+ assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000, -20), -4);
+ assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000 + 1, -20), -3);
+ assert_almost_eq!(estimate_scaling_factor(1048575, -20), 0);
+ assert_almost_eq!(estimate_scaling_factor(1048576, -20), 0);
+ assert_almost_eq!(estimate_scaling_factor(1048577, -20), 1);
+ assert_almost_eq!(estimate_scaling_factor(10485759999999999999, -20), 13);
+ assert_almost_eq!(estimate_scaling_factor(10485760000000000000, -20), 13);
+ assert_almost_eq!(estimate_scaling_factor(10485760000000000001, -20), 14);
+
+ // extreme values:
+ // 2^-1074 = 4.94065... * 10^-324
+ // (2^53-1) * 2^971 = 1.79763... * 10^308
+ assert_almost_eq!(estimate_scaling_factor(1, -1074), -323);
+ assert_almost_eq!(estimate_scaling_factor(0x1fffffffffffff, 971), 309);
+
+ for i in -1074..972 {
+ let expected = super::ldexp_f64(1.0, i).log10().ceil();
+ assert_almost_eq!(estimate_scaling_factor(1, i as i16), expected as i16);
+ }
+}
+
--- /dev/null
+// Copyright 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.
+
+use std::prelude::v1::*;
+use std::{str, mem, i16, f32, f64, fmt};
+use std::__rand as rand;
+use rand::{Rand, XorShiftRng};
+use rand::distributions::{IndependentSample, Range};
+
+use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
+use core::num::flt2dec::{MAX_SIG_DIGITS, round_up, Part, Formatted, Sign};
+use core::num::flt2dec::{to_shortest_str, to_shortest_exp_str,
+ to_exact_exp_str, to_exact_fixed_str};
+
+pub use test::Bencher;
+
+mod estimator;
+mod strategy {
+ mod dragon;
+ mod grisu;
+}
+
+pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
+ match decode(v).1 {
+ FullDecoded::Finite(decoded) => decoded,
+ full_decoded => panic!("expected finite, got {:?} instead", full_decoded)
+ }
+}
+
+macro_rules! check_shortest {
+ ($f:ident($v:expr) => $buf:expr, $exp:expr) => (
+ check_shortest!($f($v) => $buf, $exp;
+ "shortest mismatch for v={v}: actual {actual:?}, expected {expected:?}",
+ v = stringify!($v))
+ );
+
+ ($f:ident{$($k:ident: $v:expr),+} => $buf:expr, $exp:expr) => (
+ check_shortest!($f{$($k: $v),+} => $buf, $exp;
+ "shortest mismatch for {v:?}: actual {actual:?}, expected {expected:?}",
+ v = Decoded { $($k: $v),+ })
+ );
+
+ ($f:ident($v:expr) => $buf:expr, $exp:expr; $fmt:expr, $($key:ident = $val:expr),*) => ({
+ let mut buf = [b'_'; MAX_SIG_DIGITS];
+ let (len, k) = $f(&decode_finite($v), &mut buf);
+ assert!((&buf[..len], k) == ($buf, $exp),
+ $fmt, actual = (str::from_utf8(&buf[..len]).unwrap(), k),
+ expected = (str::from_utf8($buf).unwrap(), $exp),
+ $($key = $val),*);
+ });
+
+ ($f:ident{$($k:ident: $v:expr),+} => $buf:expr, $exp:expr;
+ $fmt:expr, $($key:ident = $val:expr),*) => ({
+ let mut buf = [b'_'; MAX_SIG_DIGITS];
+ let (len, k) = $f(&Decoded { $($k: $v),+ }, &mut buf);
+ assert!((&buf[..len], k) == ($buf, $exp),
+ $fmt, actual = (str::from_utf8(&buf[..len]).unwrap(), k),
+ expected = (str::from_utf8($buf).unwrap(), $exp),
+ $($key = $val),*);
+ })
+}
+
+macro_rules! try_exact {
+ ($f:ident($decoded:expr) => $buf:expr, $expected:expr, $expectedk:expr;
+ $fmt:expr, $($key:ident = $val:expr),*) => ({
+ let (len, k) = $f($decoded, &mut $buf[..$expected.len()], i16::MIN);
+ assert!((&$buf[..len], k) == ($expected, $expectedk),
+ $fmt, actual = (str::from_utf8(&$buf[..len]).unwrap(), k),
+ expected = (str::from_utf8($expected).unwrap(), $expectedk),
+ $($key = $val),*);
+ })
+}
+
+macro_rules! try_fixed {
+ ($f:ident($decoded:expr) => $buf:expr, $request:expr, $expected:expr, $expectedk:expr;
+ $fmt:expr, $($key:ident = $val:expr),*) => ({
+ let (len, k) = $f($decoded, &mut $buf[..], $request);
+ assert!((&$buf[..len], k) == ($expected, $expectedk),
+ $fmt, actual = (str::from_utf8(&$buf[..len]).unwrap(), k),
+ expected = (str::from_utf8($expected).unwrap(), $expectedk),
+ $($key = $val),*);
+ })
+}
+
+fn ldexp_f32(a: f32, b: i32) -> f32 {
+ ldexp_f64(a as f64, b) as f32
+}
+
+fn ldexp_f64(a: f64, b: i32) -> f64 {
+ extern {
+ fn ldexp(x: f64, n: i32) -> f64;
+ }
+ unsafe { ldexp(a, b) }
+}
+
+fn check_exact<F, T>(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16)
+ where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+ // use a large enough buffer
+ let mut buf = [b'_'; 1024];
+ let mut expected_ = [b'_'; 1024];
+
+ let decoded = decode_finite(v);
+ let cut = expected.iter().position(|&c| c == b' ');
+
+ // check significant digits
+ for i in 1..cut.unwrap_or(expected.len() - 1) {
+ expected_[..i].copy_from_slice(&expected[..i]);
+ let mut expectedk_ = expectedk;
+ if expected[i] >= b'5' {
+ // check if this is a rounding-to-even case.
+ // we avoid rounding ...x5000... (with infinite zeroes) to ...(x+1) when x is even.
+ if !(i+1 < expected.len() && expected[i-1] & 1 == 0 &&
+ expected[i] == b'5' &&
+ expected[i+1] == b' ') {
+ // if this returns true, expected_[..i] is all `9`s and being rounded up.
+ // we should always return `100..00` (`i` digits) instead, since that's
+ // what we can came up with `i` digits anyway. `round_up` assumes that
+ // the adjustment to the length is done by caller, which we simply ignore.
+ if let Some(_) = round_up(&mut expected_, i) { expectedk_ += 1; }
+ }
+ }
+
+ try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk_;
+ "exact sigdigit mismatch for v={v}, i={i}: \
+ actual {actual:?}, expected {expected:?}",
+ v = vstr, i = i);
+ try_fixed!(f(&decoded) => &mut buf, expectedk_ - i as i16, &expected_[..i], expectedk_;
+ "fixed sigdigit mismatch for v={v}, i={i}: \
+ actual {actual:?}, expected {expected:?}",
+ v = vstr, i = i);
+ }
+
+ // check exact rounding for zero- and negative-width cases
+ let start;
+ if expected[0] >= b'5' {
+ try_fixed!(f(&decoded) => &mut buf, expectedk, b"1", expectedk + 1;
+ "zero-width rounding-up mismatch for v={v}: \
+ actual {actual:?}, expected {expected:?}",
+ v = vstr);
+ start = 1;
+ } else {
+ start = 0;
+ }
+ for i in start..-10 {
+ try_fixed!(f(&decoded) => &mut buf, expectedk - i, b"", expectedk;
+ "rounding-down mismatch for v={v}, i={i}: \
+ actual {actual:?}, expected {expected:?}",
+ v = vstr, i = -i);
+ }
+
+ // check infinite zero digits
+ if let Some(cut) = cut {
+ for i in cut..expected.len()-1 {
+ expected_[..cut].copy_from_slice(&expected[..cut]);
+ for c in &mut expected_[cut..i] { *c = b'0'; }
+
+ try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk;
+ "exact infzero mismatch for v={v}, i={i}: \
+ actual {actual:?}, expected {expected:?}",
+ v = vstr, i = i);
+ try_fixed!(f(&decoded) => &mut buf, expectedk - i as i16, &expected_[..i], expectedk;
+ "fixed infzero mismatch for v={v}, i={i}: \
+ actual {actual:?}, expected {expected:?}",
+ v = vstr, i = i);
+ }
+ }
+}
+
+trait TestableFloat : DecodableFloat + fmt::Display {
+ /// Returns `x * 2^exp`. Almost same to `std::{f32,f64}::ldexp`.
+ /// This is used for testing.
+ fn ldexpi(f: i64, exp: isize) -> Self;
+}
+
+impl TestableFloat for f32 {
+ fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() }
+}
+
+impl TestableFloat for f64 {
+ fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() }
+}
+
+fn check_exact_one<F, T>(mut f: F, x: i64, e: isize, tstr: &str, expected: &[u8], expectedk: i16)
+ where T: TestableFloat,
+ F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+ // use a large enough buffer
+ let mut buf = [b'_'; 1024];
+ let v: T = TestableFloat::ldexpi(x, e);
+ let decoded = decode_finite(v);
+
+ try_exact!(f(&decoded) => &mut buf, &expected, expectedk;
+ "exact mismatch for v={x}p{e}{t}: actual {actual:?}, expected {expected:?}",
+ x = x, e = e, t = tstr);
+ try_fixed!(f(&decoded) => &mut buf, expectedk - expected.len() as i16, &expected, expectedk;
+ "fixed mismatch for v={x}p{e}{t}: actual {actual:?}, expected {expected:?}",
+ x = x, e = e, t = tstr);
+}
+
+macro_rules! check_exact {
+ ($f:ident($v:expr) => $buf:expr, $exp:expr) => (
+ check_exact(|d,b,k| $f(d,b,k), $v, stringify!($v), $buf, $exp)
+ )
+}
+
+macro_rules! check_exact_one {
+ ($f:ident($x:expr, $e:expr; $t:ty) => $buf:expr, $exp:expr) => (
+ check_exact_one::<_, $t>(|d,b,k| $f(d,b,k), $x, $e, stringify!($t), $buf, $exp)
+ )
+}
+
+// in the following comments, three numbers are spaced by 1 ulp apart,
+// and the second one is being formatted.
+//
+// some tests are derived from [1].
+//
+// [1] Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion
+// ftp://ftp.ee.lbl.gov/testbase-report.ps.Z
+
+pub fn f32_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+ // 0.0999999940395355224609375
+ // 0.100000001490116119384765625
+ // 0.10000000894069671630859375
+ check_shortest!(f(0.1f32) => b"1", 0);
+
+ // 0.333333313465118408203125
+ // 0.3333333432674407958984375 (1/3 in the default rounding)
+ // 0.33333337306976318359375
+ check_shortest!(f(1.0f32/3.0) => b"33333334", 0);
+
+ // 10^1 * 0.31415917873382568359375
+ // 10^1 * 0.31415920257568359375
+ // 10^1 * 0.31415922641754150390625
+ check_shortest!(f(3.141592f32) => b"3141592", 1);
+
+ // 10^18 * 0.31415916243714048
+ // 10^18 * 0.314159196796878848
+ // 10^18 * 0.314159231156617216
+ check_shortest!(f(3.141592e17f32) => b"3141592", 18);
+
+ // regression test for decoders
+ // 10^8 * 0.3355443
+ // 10^8 * 0.33554432
+ // 10^8 * 0.33554436
+ check_shortest!(f(ldexp_f32(1.0, 25)) => b"33554432", 8);
+
+ // 10^39 * 0.340282326356119256160033759537265639424
+ // 10^39 * 0.34028234663852885981170418348451692544
+ // 10^39 * 0.340282366920938463463374607431768211456
+ check_shortest!(f(f32::MAX) => b"34028235", 39);
+
+ // 10^-37 * 0.1175494210692441075487029444849287348827...
+ // 10^-37 * 0.1175494350822287507968736537222245677818...
+ // 10^-37 * 0.1175494490952133940450443629595204006810...
+ check_shortest!(f(f32::MIN_POSITIVE) => b"11754944", -37);
+
+ // 10^-44 * 0
+ // 10^-44 * 0.1401298464324817070923729583289916131280...
+ // 10^-44 * 0.2802596928649634141847459166579832262560...
+ let minf32 = ldexp_f32(1.0, -149);
+ check_shortest!(f(minf32) => b"1", -44);
+}
+
+pub fn f32_exact_sanity_test<F>(mut f: F)
+ where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+ let minf32 = ldexp_f32(1.0, -149);
+
+ check_exact!(f(0.1f32) => b"100000001490116119384765625 ", 0);
+ check_exact!(f(0.5f32) => b"5 ", 0);
+ check_exact!(f(1.0f32/3.0) => b"3333333432674407958984375 ", 0);
+ check_exact!(f(3.141592f32) => b"31415920257568359375 ", 1);
+ check_exact!(f(3.141592e17f32) => b"314159196796878848 ", 18);
+ check_exact!(f(f32::MAX) => b"34028234663852885981170418348451692544 ", 39);
+ check_exact!(f(f32::MIN_POSITIVE) => b"1175494350822287507968736537222245677818", -37);
+ check_exact!(f(minf32) => b"1401298464324817070923729583289916131280", -44);
+
+ // [1], Table 16: Stress Inputs for Converting 24-bit Binary to Decimal, < 1/2 ULP
+ check_exact_one!(f(12676506, -102; f32) => b"2", -23);
+ check_exact_one!(f(12676506, -103; f32) => b"12", -23);
+ check_exact_one!(f(15445013, 86; f32) => b"119", 34);
+ check_exact_one!(f(13734123, -138; f32) => b"3941", -34);
+ check_exact_one!(f(12428269, -130; f32) => b"91308", -32);
+ check_exact_one!(f(15334037, -146; f32) => b"171900", -36);
+ check_exact_one!(f(11518287, -41; f32) => b"5237910", -5);
+ check_exact_one!(f(12584953, -145; f32) => b"28216440", -36);
+ check_exact_one!(f(15961084, -125; f32) => b"375243281", -30);
+ check_exact_one!(f(14915817, -146; f32) => b"1672120916", -36);
+ check_exact_one!(f(10845484, -102; f32) => b"21388945814", -23);
+ check_exact_one!(f(16431059, -61; f32) => b"712583594561", -11);
+
+ // [1], Table 17: Stress Inputs for Converting 24-bit Binary to Decimal, > 1/2 ULP
+ check_exact_one!(f(16093626, 69; f32) => b"1", 29);
+ check_exact_one!(f( 9983778, 25; f32) => b"34", 15);
+ check_exact_one!(f(12745034, 104; f32) => b"259", 39);
+ check_exact_one!(f(12706553, 72; f32) => b"6001", 29);
+ check_exact_one!(f(11005028, 45; f32) => b"38721", 21);
+ check_exact_one!(f(15059547, 71; f32) => b"355584", 29);
+ check_exact_one!(f(16015691, -99; f32) => b"2526831", -22);
+ check_exact_one!(f( 8667859, 56; f32) => b"62458507", 24);
+ check_exact_one!(f(14855922, -82; f32) => b"307213267", -17);
+ check_exact_one!(f(14855922, -83; f32) => b"1536066333", -17);
+ check_exact_one!(f(10144164, -110; f32) => b"78147796834", -26);
+ check_exact_one!(f(13248074, 95; f32) => b"524810279937", 36);
+}
+
+pub fn f64_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+ // 0.0999999999999999777955395074968691915273...
+ // 0.1000000000000000055511151231257827021181...
+ // 0.1000000000000000333066907387546962127089...
+ check_shortest!(f(0.1f64) => b"1", 0);
+
+ // this example is explicitly mentioned in the paper.
+ // 10^3 * 0.0999999999999999857891452847979962825775...
+ // 10^3 * 0.1 (exact)
+ // 10^3 * 0.1000000000000000142108547152020037174224...
+ check_shortest!(f(100.0f64) => b"1", 3);
+
+ // 0.3333333333333332593184650249895639717578...
+ // 0.3333333333333333148296162562473909929394... (1/3 in the default rounding)
+ // 0.3333333333333333703407674875052180141210...
+ check_shortest!(f(1.0f64/3.0) => b"3333333333333333", 0);
+
+ // explicit test case for equally closest representations.
+ // Dragon has its own tie-breaking rule; Grisu should fall back.
+ // 10^1 * 0.1000007629394531027955395074968691915273...
+ // 10^1 * 0.100000762939453125 (exact)
+ // 10^1 * 0.1000007629394531472044604925031308084726...
+ check_shortest!(f(1.00000762939453125f64) => b"10000076293945313", 1);
+
+ // 10^1 * 0.3141591999999999718085064159822650253772...
+ // 10^1 * 0.3141592000000000162174274009885266423225...
+ // 10^1 * 0.3141592000000000606263483859947882592678...
+ check_shortest!(f(3.141592f64) => b"3141592", 1);
+
+ // 10^18 * 0.314159199999999936
+ // 10^18 * 0.3141592 (exact)
+ // 10^18 * 0.314159200000000064
+ check_shortest!(f(3.141592e17f64) => b"3141592", 18);
+
+ // regression test for decoders
+ // 10^20 * 0.18446744073709549568
+ // 10^20 * 0.18446744073709551616
+ // 10^20 * 0.18446744073709555712
+ check_shortest!(f(ldexp_f64(1.0, 64)) => b"18446744073709552", 20);
+
+ // pathological case: high = 10^23 (exact). tie breaking should always prefer that.
+ // 10^24 * 0.099999999999999974834176
+ // 10^24 * 0.099999999999999991611392
+ // 10^24 * 0.100000000000000008388608
+ check_shortest!(f(1.0e23f64) => b"1", 24);
+
+ // 10^309 * 0.1797693134862315508561243283845062402343...
+ // 10^309 * 0.1797693134862315708145274237317043567980...
+ // 10^309 * 0.1797693134862315907729305190789024733617...
+ check_shortest!(f(f64::MAX) => b"17976931348623157", 309);
+
+ // 10^-307 * 0.2225073858507200889024586876085859887650...
+ // 10^-307 * 0.2225073858507201383090232717332404064219...
+ // 10^-307 * 0.2225073858507201877155878558578948240788...
+ check_shortest!(f(f64::MIN_POSITIVE) => b"22250738585072014", -307);
+
+ // 10^-323 * 0
+ // 10^-323 * 0.4940656458412465441765687928682213723650...
+ // 10^-323 * 0.9881312916824930883531375857364427447301...
+ let minf64 = ldexp_f64(1.0, -1074);
+ check_shortest!(f(minf64) => b"5", -323);
+}
+
+pub fn f64_exact_sanity_test<F>(mut f: F)
+ where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+ let minf64 = ldexp_f64(1.0, -1074);
+
+ check_exact!(f(0.1f64) => b"1000000000000000055511151231257827021181", 0);
+ check_exact!(f(0.45f64) => b"4500000000000000111022302462515654042363", 0);
+ check_exact!(f(0.5f64) => b"5 ", 0);
+ check_exact!(f(0.95f64) => b"9499999999999999555910790149937383830547", 0);
+ check_exact!(f(100.0f64) => b"1 ", 3);
+ check_exact!(f(999.5f64) => b"9995000000000000000000000000000000000000", 3);
+ check_exact!(f(1.0f64/3.0) => b"3333333333333333148296162562473909929394", 0);
+ check_exact!(f(3.141592f64) => b"3141592000000000162174274009885266423225", 1);
+ check_exact!(f(3.141592e17f64) => b"3141592 ", 18);
+ check_exact!(f(1.0e23f64) => b"99999999999999991611392 ", 23);
+ check_exact!(f(f64::MAX) => b"1797693134862315708145274237317043567980", 309);
+ check_exact!(f(f64::MIN_POSITIVE) => b"2225073858507201383090232717332404064219", -307);
+ check_exact!(f(minf64) => b"4940656458412465441765687928682213723650\
+ 5980261432476442558568250067550727020875\
+ 1865299836361635992379796564695445717730\
+ 9266567103559397963987747960107818781263\
+ 0071319031140452784581716784898210368871\
+ 8636056998730723050006387409153564984387\
+ 3124733972731696151400317153853980741262\
+ 3856559117102665855668676818703956031062\
+ 4931945271591492455329305456544401127480\
+ 1297099995419319894090804165633245247571\
+ 4786901472678015935523861155013480352649\
+ 3472019379026810710749170333222684475333\
+ 5720832431936092382893458368060106011506\
+ 1698097530783422773183292479049825247307\
+ 7637592724787465608477820373446969953364\
+ 7017972677717585125660551199131504891101\
+ 4510378627381672509558373897335989936648\
+ 0994116420570263709027924276754456522908\
+ 7538682506419718265533447265625 ", -323);
+
+ // [1], Table 3: Stress Inputs for Converting 53-bit Binary to Decimal, < 1/2 ULP
+ check_exact_one!(f(8511030020275656, -342; f64) => b"9", -87);
+ check_exact_one!(f(5201988407066741, -824; f64) => b"46", -232);
+ check_exact_one!(f(6406892948269899, 237; f64) => b"141", 88);
+ check_exact_one!(f(8431154198732492, 72; f64) => b"3981", 38);
+ check_exact_one!(f(6475049196144587, 99; f64) => b"41040", 46);
+ check_exact_one!(f(8274307542972842, 726; f64) => b"292084", 235);
+ check_exact_one!(f(5381065484265332, -456; f64) => b"2891946", -121);
+ check_exact_one!(f(6761728585499734, -1057; f64) => b"43787718", -302);
+ check_exact_one!(f(7976538478610756, 376; f64) => b"122770163", 130);
+ check_exact_one!(f(5982403858958067, 377; f64) => b"1841552452", 130);
+ check_exact_one!(f(5536995190630837, 93; f64) => b"54835744350", 44);
+ check_exact_one!(f(7225450889282194, 710; f64) => b"389190181146", 230);
+ check_exact_one!(f(7225450889282194, 709; f64) => b"1945950905732", 230);
+ check_exact_one!(f(8703372741147379, 117; f64) => b"14460958381605", 52);
+ check_exact_one!(f(8944262675275217, -1001; f64) => b"417367747458531", -285);
+ check_exact_one!(f(7459803696087692, -707; f64) => b"1107950772878888", -196);
+ check_exact_one!(f(6080469016670379, -381; f64) => b"12345501366327440", -98);
+ check_exact_one!(f(8385515147034757, 721; f64) => b"925031711960365024", 233);
+ check_exact_one!(f(7514216811389786, -828; f64) => b"4198047150284889840", -233);
+ check_exact_one!(f(8397297803260511, -345; f64) => b"11716315319786511046", -87);
+ check_exact_one!(f(6733459239310543, 202; f64) => b"432810072844612493629", 77);
+ check_exact_one!(f(8091450587292794, -473; f64) => b"3317710118160031081518", -126);
+
+ // [1], Table 4: Stress Inputs for Converting 53-bit Binary to Decimal, > 1/2 ULP
+ check_exact_one!(f(6567258882077402, 952; f64) => b"3", 303);
+ check_exact_one!(f(6712731423444934, 535; f64) => b"76", 177);
+ check_exact_one!(f(6712731423444934, 534; f64) => b"378", 177);
+ check_exact_one!(f(5298405411573037, -957; f64) => b"4350", -272);
+ check_exact_one!(f(5137311167659507, -144; f64) => b"23037", -27);
+ check_exact_one!(f(6722280709661868, 363; f64) => b"126301", 126);
+ check_exact_one!(f(5344436398034927, -169; f64) => b"7142211", -35);
+ check_exact_one!(f(8369123604277281, -853; f64) => b"13934574", -240);
+ check_exact_one!(f(8995822108487663, -780; f64) => b"141463449", -218);
+ check_exact_one!(f(8942832835564782, -383; f64) => b"4539277920", -99);
+ check_exact_one!(f(8942832835564782, -384; f64) => b"22696389598", -99);
+ check_exact_one!(f(8942832835564782, -385; f64) => b"113481947988", -99);
+ check_exact_one!(f(6965949469487146, -249; f64) => b"7700366561890", -59);
+ check_exact_one!(f(6965949469487146, -250; f64) => b"38501832809448", -59);
+ check_exact_one!(f(6965949469487146, -251; f64) => b"192509164047238", -59);
+ check_exact_one!(f(7487252720986826, 548; f64) => b"6898586531774201", 181);
+ check_exact_one!(f(5592117679628511, 164; f64) => b"13076622631878654", 66);
+ check_exact_one!(f(8887055249355788, 665; f64) => b"136052020756121240", 217);
+ check_exact_one!(f(6994187472632449, 690; f64) => b"3592810217475959676", 224);
+ check_exact_one!(f(8797576579012143, 588; f64) => b"89125197712484551899", 193);
+ check_exact_one!(f(7363326733505337, 272; f64) => b"558769757362301140950", 98);
+ check_exact_one!(f(8549497411294502, -448; f64) => b"1176257830728540379990", -118);
+}
+
+pub fn more_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+ check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1,
+ exp: 0, inclusive: true} => b"1", 18);
+ check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1,
+ exp: 0, inclusive: false} => b"99999999999999999", 17);
+}
+
+fn iterate<F, G, V>(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V) -> (usize, usize)
+ where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+ G: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
+ V: FnMut(usize) -> Decoded {
+ assert!(k <= 1024);
+
+ let mut npassed = 0; // f(x) = Some(g(x))
+ let mut nignored = 0; // f(x) = None
+
+ for i in 0..n {
+ if (i & 0xfffff) == 0 {
+ println!("in progress, {:x}/{:x} (ignored={} passed={} failed={})",
+ i, n, nignored, npassed, i - nignored - npassed);
+ }
+
+ let decoded = v(i);
+ let mut buf1 = [0; 1024];
+ if let Some((len1, e1)) = f(&decoded, &mut buf1[..k]) {
+ let mut buf2 = [0; 1024];
+ let (len2, e2) = g(&decoded, &mut buf2[..k]);
+ if e1 == e2 && &buf1[..len1] == &buf2[..len2] {
+ npassed += 1;
+ } else {
+ println!("equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}",
+ i, n, decoded, str::from_utf8(&buf1[..len1]).unwrap(), e1,
+ str::from_utf8(&buf2[..len2]).unwrap(), e2);
+ }
+ } else {
+ nignored += 1;
+ }
+ }
+ println!("{}({}): done, ignored={} passed={} failed={}",
+ func, k, nignored, npassed, n - nignored - npassed);
+ assert!(nignored + npassed == n,
+ "{}({}): {} out of {} values returns an incorrect value!",
+ func, k, n - nignored - npassed, n);
+ (npassed, nignored)
+}
+
+pub fn f32_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
+ where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+ G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+ let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng());
+ let f32_range = Range::new(0x0000_0001u32, 0x7f80_0000);
+ iterate("f32_random_equivalence_test", k, n, f, g, |_| {
+ let i: u32 = f32_range.ind_sample(&mut rng);
+ let x: f32 = unsafe {mem::transmute(i)};
+ decode_finite(x)
+ });
+}
+
+pub fn f64_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
+ where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+ G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+ let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng());
+ let f64_range = Range::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000);
+ iterate("f64_random_equivalence_test", k, n, f, g, |_| {
+ let i: u64 = f64_range.ind_sample(&mut rng);
+ let x: f64 = unsafe {mem::transmute(i)};
+ decode_finite(x)
+ });
+}
+
+pub fn f32_exhaustive_equivalence_test<F, G>(f: F, g: G, k: usize)
+ where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+ G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+ // we have only 2^23 * (2^8 - 1) - 1 = 2,139,095,039 positive finite f32 values,
+ // so why not simply testing all of them?
+ //
+ // this is of course very stressful (and thus should be behind an `#[ignore]` attribute),
+ // but with `-C opt-level=3 -C lto` this only takes about an hour or so.
+
+ // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e. all finite ranges
+ let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test",
+ k, 0x7f7f_ffff, f, g, |i: usize| {
+ let x: f32 = unsafe {mem::transmute(i as u32 + 1)};
+ decode_finite(x)
+ });
+ assert_eq!((npassed, nignored), (2121451881, 17643158));
+}
+
+fn to_string_with_parts<F>(mut f: F) -> String
+ where F: for<'a> FnMut(&'a mut [u8], &'a mut [Part<'a>]) -> Formatted<'a> {
+ let mut buf = [0; 1024];
+ let mut parts = [Part::Zero(0); 16];
+ let formatted = f(&mut buf, &mut parts);
+ let mut ret = vec![0; formatted.len()];
+ assert_eq!(formatted.write(&mut ret), Some(ret.len()));
+ String::from_utf8(ret).unwrap()
+}
+
+pub fn to_shortest_str_test<F>(mut f_: F)
+ where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+ use core::num::flt2dec::Sign::*;
+
+ fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String
+ where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+ to_string_with_parts(|buf, parts| to_shortest_str(|d,b| f(d,b), v, sign,
+ frac_digits, upper, buf, parts))
+ }
+
+ let f = &mut f_;
+
+ assert_eq!(to_string(f, 0.0, Minus, 0, false), "0");
+ assert_eq!(to_string(f, 0.0, MinusRaw, 0, false), "0");
+ assert_eq!(to_string(f, 0.0, MinusPlus, 0, false), "+0");
+ assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0, false), "+0");
+ assert_eq!(to_string(f, -0.0, Minus, 0, false), "0");
+ assert_eq!(to_string(f, -0.0, MinusRaw, 0, false), "-0");
+ assert_eq!(to_string(f, -0.0, MinusPlus, 0, false), "+0");
+ assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0");
+ assert_eq!(to_string(f, 0.0, Minus, 1, true), "0.0");
+ assert_eq!(to_string(f, 0.0, MinusRaw, 1, true), "0.0");
+ assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0.0");
+ assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, true), "+0.0");
+ assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.00000000");
+ assert_eq!(to_string(f, -0.0, MinusRaw, 8, true), "-0.00000000");
+ assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.00000000");
+ assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, true), "-0.00000000");
+
+ assert_eq!(to_string(f, 1.0/0.0, Minus, 0, false), "inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusRaw, 0, true), "inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusPlus, 0, false), "+inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, 0, true), "+inf");
+ assert_eq!(to_string(f, 0.0/0.0, Minus, 0, false), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusRaw, 1, true), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusPlus, 8, false), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, 64, true), "NaN");
+ assert_eq!(to_string(f, -1.0/0.0, Minus, 0, false), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusRaw, 1, true), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusPlus, 8, false), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64, true), "-inf");
+
+ assert_eq!(to_string(f, 3.14, Minus, 0, false), "3.14");
+ assert_eq!(to_string(f, 3.14, MinusRaw, 0, false), "3.14");
+ assert_eq!(to_string(f, 3.14, MinusPlus, 0, false), "+3.14");
+ assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0, false), "+3.14");
+ assert_eq!(to_string(f, -3.14, Minus, 0, false), "-3.14");
+ assert_eq!(to_string(f, -3.14, MinusRaw, 0, false), "-3.14");
+ assert_eq!(to_string(f, -3.14, MinusPlus, 0, false), "-3.14");
+ assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3.14");
+ assert_eq!(to_string(f, 3.14, Minus, 1, true), "3.14");
+ assert_eq!(to_string(f, 3.14, MinusRaw, 2, true), "3.14");
+ assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.140");
+ assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4, true), "+3.1400");
+ assert_eq!(to_string(f, -3.14, Minus, 8, true), "-3.14000000");
+ assert_eq!(to_string(f, -3.14, MinusRaw, 8, true), "-3.14000000");
+ assert_eq!(to_string(f, -3.14, MinusPlus, 8, true), "-3.14000000");
+ assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8, true), "-3.14000000");
+
+ assert_eq!(to_string(f, 7.5e-11, Minus, 0, false), "0.000000000075");
+ assert_eq!(to_string(f, 7.5e-11, Minus, 3, false), "0.000000000075");
+ assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075");
+ assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750");
+
+ assert_eq!(to_string(f, 1.9971e20, Minus, 0, false), "199710000000000000000");
+ assert_eq!(to_string(f, 1.9971e20, Minus, 1, false), "199710000000000000000.0");
+ assert_eq!(to_string(f, 1.9971e20, Minus, 8, false), "199710000000000000000.00000000");
+
+ assert_eq!(to_string(f, f32::MAX, Minus, 0, false), format!("34028235{:0>31}", ""));
+ assert_eq!(to_string(f, f32::MAX, Minus, 1, false), format!("34028235{:0>31}.0", ""));
+ assert_eq!(to_string(f, f32::MAX, Minus, 8, false), format!("34028235{:0>31}.00000000", ""));
+
+ let minf32 = ldexp_f32(1.0, -149);
+ assert_eq!(to_string(f, minf32, Minus, 0, false), format!("0.{:0>44}1", ""));
+ assert_eq!(to_string(f, minf32, Minus, 45, false), format!("0.{:0>44}1", ""));
+ assert_eq!(to_string(f, minf32, Minus, 46, false), format!("0.{:0>44}10", ""));
+
+ assert_eq!(to_string(f, f64::MAX, Minus, 0, false),
+ format!("17976931348623157{:0>292}", ""));
+ assert_eq!(to_string(f, f64::MAX, Minus, 1, false),
+ format!("17976931348623157{:0>292}.0", ""));
+ assert_eq!(to_string(f, f64::MAX, Minus, 8, false),
+ format!("17976931348623157{:0>292}.00000000", ""));
+
+ let minf64 = ldexp_f64(1.0, -1074);
+ assert_eq!(to_string(f, minf64, Minus, 0, false), format!("0.{:0>323}5", ""));
+ assert_eq!(to_string(f, minf64, Minus, 324, false), format!("0.{:0>323}5", ""));
+ assert_eq!(to_string(f, minf64, Minus, 325, false), format!("0.{:0>323}50", ""));
+
+ // very large output
+ assert_eq!(to_string(f, 1.1, Minus, 80000, false), format!("1.1{:0>79999}", ""));
+}
+
+pub fn to_shortest_exp_str_test<F>(mut f_: F)
+ where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+ use core::num::flt2dec::Sign::*;
+
+ fn to_string<T, F>(f: &mut F, v: T, sign: Sign, exp_bounds: (i16, i16), upper: bool) -> String
+ where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+ to_string_with_parts(|buf, parts| to_shortest_exp_str(|d,b| f(d,b), v, sign,
+ exp_bounds, upper, buf, parts))
+ }
+
+ let f = &mut f_;
+
+ assert_eq!(to_string(f, 0.0, Minus, (-4, 16), false), "0");
+ assert_eq!(to_string(f, 0.0, MinusRaw, (-4, 16), false), "0");
+ assert_eq!(to_string(f, 0.0, MinusPlus, (-4, 16), false), "+0");
+ assert_eq!(to_string(f, 0.0, MinusPlusRaw, (-4, 16), false), "+0");
+ assert_eq!(to_string(f, -0.0, Minus, (-4, 16), false), "0");
+ assert_eq!(to_string(f, -0.0, MinusRaw, (-4, 16), false), "-0");
+ assert_eq!(to_string(f, -0.0, MinusPlus, (-4, 16), false), "+0");
+ assert_eq!(to_string(f, -0.0, MinusPlusRaw, (-4, 16), false), "-0");
+ assert_eq!(to_string(f, 0.0, Minus, ( 0, 0), true), "0E0");
+ assert_eq!(to_string(f, 0.0, MinusRaw, ( 0, 0), false), "0e0");
+ assert_eq!(to_string(f, 0.0, MinusPlus, (-9, -5), true), "+0E0");
+ assert_eq!(to_string(f, 0.0, MinusPlusRaw, ( 5, 9), false), "+0e0");
+ assert_eq!(to_string(f, -0.0, Minus, ( 0, 0), true), "0E0");
+ assert_eq!(to_string(f, -0.0, MinusRaw, ( 0, 0), false), "-0e0");
+ assert_eq!(to_string(f, -0.0, MinusPlus, (-9, -5), true), "+0E0");
+ assert_eq!(to_string(f, -0.0, MinusPlusRaw, ( 5, 9), false), "-0e0");
+
+ assert_eq!(to_string(f, 1.0/0.0, Minus, (-4, 16), false), "inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusRaw, (-4, 16), true), "inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusPlus, (-4, 16), false), "+inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, (-4, 16), true), "+inf");
+ assert_eq!(to_string(f, 0.0/0.0, Minus, ( 0, 0), false), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusRaw, ( 0, 0), true), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusPlus, (-9, -5), false), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, ( 5, 9), true), "NaN");
+ assert_eq!(to_string(f, -1.0/0.0, Minus, ( 0, 0), false), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusRaw, ( 0, 0), true), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusPlus, (-9, -5), false), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, ( 5, 9), true), "-inf");
+
+ assert_eq!(to_string(f, 3.14, Minus, (-4, 16), false), "3.14");
+ assert_eq!(to_string(f, 3.14, MinusRaw, (-4, 16), false), "3.14");
+ assert_eq!(to_string(f, 3.14, MinusPlus, (-4, 16), false), "+3.14");
+ assert_eq!(to_string(f, 3.14, MinusPlusRaw, (-4, 16), false), "+3.14");
+ assert_eq!(to_string(f, -3.14, Minus, (-4, 16), false), "-3.14");
+ assert_eq!(to_string(f, -3.14, MinusRaw, (-4, 16), false), "-3.14");
+ assert_eq!(to_string(f, -3.14, MinusPlus, (-4, 16), false), "-3.14");
+ assert_eq!(to_string(f, -3.14, MinusPlusRaw, (-4, 16), false), "-3.14");
+ assert_eq!(to_string(f, 3.14, Minus, ( 0, 0), true), "3.14E0");
+ assert_eq!(to_string(f, 3.14, MinusRaw, ( 0, 0), false), "3.14e0");
+ assert_eq!(to_string(f, 3.14, MinusPlus, (-9, -5), true), "+3.14E0");
+ assert_eq!(to_string(f, 3.14, MinusPlusRaw, ( 5, 9), false), "+3.14e0");
+ assert_eq!(to_string(f, -3.14, Minus, ( 0, 0), true), "-3.14E0");
+ assert_eq!(to_string(f, -3.14, MinusRaw, ( 0, 0), false), "-3.14e0");
+ assert_eq!(to_string(f, -3.14, MinusPlus, (-9, -5), true), "-3.14E0");
+ assert_eq!(to_string(f, -3.14, MinusPlusRaw, ( 5, 9), false), "-3.14e0");
+
+ assert_eq!(to_string(f, 0.1, Minus, (-4, 16), false), "0.1");
+ assert_eq!(to_string(f, 0.1, MinusRaw, (-4, 16), false), "0.1");
+ assert_eq!(to_string(f, 0.1, MinusPlus, (-4, 16), false), "+0.1");
+ assert_eq!(to_string(f, 0.1, MinusPlusRaw, (-4, 16), false), "+0.1");
+ assert_eq!(to_string(f, -0.1, Minus, (-4, 16), false), "-0.1");
+ assert_eq!(to_string(f, -0.1, MinusRaw, (-4, 16), false), "-0.1");
+ assert_eq!(to_string(f, -0.1, MinusPlus, (-4, 16), false), "-0.1");
+ assert_eq!(to_string(f, -0.1, MinusPlusRaw, (-4, 16), false), "-0.1");
+ assert_eq!(to_string(f, 0.1, Minus, ( 0, 0), true), "1E-1");
+ assert_eq!(to_string(f, 0.1, MinusRaw, ( 0, 0), false), "1e-1");
+ assert_eq!(to_string(f, 0.1, MinusPlus, (-9, -5), true), "+1E-1");
+ assert_eq!(to_string(f, 0.1, MinusPlusRaw, ( 5, 9), false), "+1e-1");
+ assert_eq!(to_string(f, -0.1, Minus, ( 0, 0), true), "-1E-1");
+ assert_eq!(to_string(f, -0.1, MinusRaw, ( 0, 0), false), "-1e-1");
+ assert_eq!(to_string(f, -0.1, MinusPlus, (-9, -5), true), "-1E-1");
+ assert_eq!(to_string(f, -0.1, MinusPlusRaw, ( 5, 9), false), "-1e-1");
+
+ assert_eq!(to_string(f, 7.5e-11, Minus, ( -4, 16), false), "7.5e-11");
+ assert_eq!(to_string(f, 7.5e-11, Minus, (-11, 10), false), "0.000000000075");
+ assert_eq!(to_string(f, 7.5e-11, Minus, (-10, 11), false), "7.5e-11");
+
+ assert_eq!(to_string(f, 1.9971e20, Minus, ( -4, 16), false), "1.9971e20");
+ assert_eq!(to_string(f, 1.9971e20, Minus, (-20, 21), false), "199710000000000000000");
+ assert_eq!(to_string(f, 1.9971e20, Minus, (-21, 20), false), "1.9971e20");
+
+ // the true value of 1.0e23f64 is less than 10^23, but that shouldn't matter here
+ assert_eq!(to_string(f, 1.0e23, Minus, (22, 23), false), "1e23");
+ assert_eq!(to_string(f, 1.0e23, Minus, (23, 24), false), "100000000000000000000000");
+ assert_eq!(to_string(f, 1.0e23, Minus, (24, 25), false), "1e23");
+
+ assert_eq!(to_string(f, f32::MAX, Minus, ( -4, 16), false), "3.4028235e38");
+ assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), "3.4028235e38");
+ assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), format!("34028235{:0>31}", ""));
+
+ let minf32 = ldexp_f32(1.0, -149);
+ assert_eq!(to_string(f, minf32, Minus, ( -4, 16), false), "1e-45");
+ assert_eq!(to_string(f, minf32, Minus, (-44, 45), false), "1e-45");
+ assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), format!("0.{:0>44}1", ""));
+
+ assert_eq!(to_string(f, f64::MAX, Minus, ( -4, 16), false),
+ "1.7976931348623157e308");
+ assert_eq!(to_string(f, f64::MAX, Minus, (-308, 309), false),
+ format!("17976931348623157{:0>292}", ""));
+ assert_eq!(to_string(f, f64::MAX, Minus, (-309, 308), false),
+ "1.7976931348623157e308");
+
+ let minf64 = ldexp_f64(1.0, -1074);
+ assert_eq!(to_string(f, minf64, Minus, ( -4, 16), false), "5e-324");
+ assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), format!("0.{:0>323}5", ""));
+ assert_eq!(to_string(f, minf64, Minus, (-323, 324), false), "5e-324");
+
+ assert_eq!(to_string(f, 1.1, Minus, (i16::MIN, i16::MAX), false), "1.1");
+}
+
+pub fn to_exact_exp_str_test<F>(mut f_: F)
+ where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+ use core::num::flt2dec::Sign::*;
+
+ fn to_string<T, F>(f: &mut F, v: T, sign: Sign, ndigits: usize, upper: bool) -> String
+ where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+ to_string_with_parts(|buf, parts| to_exact_exp_str(|d,b,l| f(d,b,l), v, sign,
+ ndigits, upper, buf, parts))
+ }
+
+ let f = &mut f_;
+
+ assert_eq!(to_string(f, 0.0, Minus, 1, true), "0E0");
+ assert_eq!(to_string(f, 0.0, MinusRaw, 1, false), "0e0");
+ assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0E0");
+ assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, false), "+0e0");
+ assert_eq!(to_string(f, -0.0, Minus, 1, true), "0E0");
+ assert_eq!(to_string(f, -0.0, MinusRaw, 1, false), "-0e0");
+ assert_eq!(to_string(f, -0.0, MinusPlus, 1, true), "+0E0");
+ assert_eq!(to_string(f, -0.0, MinusPlusRaw, 1, false), "-0e0");
+ assert_eq!(to_string(f, 0.0, Minus, 2, true), "0.0E0");
+ assert_eq!(to_string(f, 0.0, MinusRaw, 2, false), "0.0e0");
+ assert_eq!(to_string(f, 0.0, MinusPlus, 2, true), "+0.0E0");
+ assert_eq!(to_string(f, 0.0, MinusPlusRaw, 2, false), "+0.0e0");
+ assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.0000000E0");
+ assert_eq!(to_string(f, -0.0, MinusRaw, 8, false), "-0.0000000e0");
+ assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.0000000E0");
+ assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, false), "-0.0000000e0");
+
+ assert_eq!(to_string(f, 1.0/0.0, Minus, 1, false), "inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusRaw, 1, true), "inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusPlus, 1, false), "+inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, 1, true), "+inf");
+ assert_eq!(to_string(f, 0.0/0.0, Minus, 8, false), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusRaw, 8, true), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusPlus, 8, false), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, 8, true), "NaN");
+ assert_eq!(to_string(f, -1.0/0.0, Minus, 64, false), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusRaw, 64, true), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusPlus, 64, false), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64, true), "-inf");
+
+ assert_eq!(to_string(f, 3.14, Minus, 1, true), "3E0");
+ assert_eq!(to_string(f, 3.14, MinusRaw, 1, false), "3e0");
+ assert_eq!(to_string(f, 3.14, MinusPlus, 1, true), "+3E0");
+ assert_eq!(to_string(f, 3.14, MinusPlusRaw, 1, false), "+3e0");
+ assert_eq!(to_string(f, -3.14, Minus, 2, true), "-3.1E0");
+ assert_eq!(to_string(f, -3.14, MinusRaw, 2, false), "-3.1e0");
+ assert_eq!(to_string(f, -3.14, MinusPlus, 2, true), "-3.1E0");
+ assert_eq!(to_string(f, -3.14, MinusPlusRaw, 2, false), "-3.1e0");
+ assert_eq!(to_string(f, 3.14, Minus, 3, true), "3.14E0");
+ assert_eq!(to_string(f, 3.14, MinusRaw, 3, false), "3.14e0");
+ assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.14E0");
+ assert_eq!(to_string(f, 3.14, MinusPlusRaw, 3, false), "+3.14e0");
+ assert_eq!(to_string(f, -3.14, Minus, 4, true), "-3.140E0");
+ assert_eq!(to_string(f, -3.14, MinusRaw, 4, false), "-3.140e0");
+ assert_eq!(to_string(f, -3.14, MinusPlus, 4, true), "-3.140E0");
+ assert_eq!(to_string(f, -3.14, MinusPlusRaw, 4, false), "-3.140e0");
+
+ assert_eq!(to_string(f, 0.195, Minus, 1, false), "2e-1");
+ assert_eq!(to_string(f, 0.195, MinusRaw, 1, true), "2E-1");
+ assert_eq!(to_string(f, 0.195, MinusPlus, 1, false), "+2e-1");
+ assert_eq!(to_string(f, 0.195, MinusPlusRaw, 1, true), "+2E-1");
+ assert_eq!(to_string(f, -0.195, Minus, 2, false), "-2.0e-1");
+ assert_eq!(to_string(f, -0.195, MinusRaw, 2, true), "-2.0E-1");
+ assert_eq!(to_string(f, -0.195, MinusPlus, 2, false), "-2.0e-1");
+ assert_eq!(to_string(f, -0.195, MinusPlusRaw, 2, true), "-2.0E-1");
+ assert_eq!(to_string(f, 0.195, Minus, 3, false), "1.95e-1");
+ assert_eq!(to_string(f, 0.195, MinusRaw, 3, true), "1.95E-1");
+ assert_eq!(to_string(f, 0.195, MinusPlus, 3, false), "+1.95e-1");
+ assert_eq!(to_string(f, 0.195, MinusPlusRaw, 3, true), "+1.95E-1");
+ assert_eq!(to_string(f, -0.195, Minus, 4, false), "-1.950e-1");
+ assert_eq!(to_string(f, -0.195, MinusRaw, 4, true), "-1.950E-1");
+ assert_eq!(to_string(f, -0.195, MinusPlus, 4, false), "-1.950e-1");
+ assert_eq!(to_string(f, -0.195, MinusPlusRaw, 4, true), "-1.950E-1");
+
+ assert_eq!(to_string(f, 9.5, Minus, 1, false), "1e1");
+ assert_eq!(to_string(f, 9.5, Minus, 2, false), "9.5e0");
+ assert_eq!(to_string(f, 9.5, Minus, 3, false), "9.50e0");
+ assert_eq!(to_string(f, 9.5, Minus, 30, false), "9.50000000000000000000000000000e0");
+
+ assert_eq!(to_string(f, 1.0e25, Minus, 1, false), "1e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 2, false), "1.0e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 15, false), "1.00000000000000e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 16, false), "1.000000000000000e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 17, false), "1.0000000000000001e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 18, false), "1.00000000000000009e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 19, false), "1.000000000000000091e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 20, false), "1.0000000000000000906e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 21, false), "1.00000000000000009060e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 22, false), "1.000000000000000090597e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 23, false), "1.0000000000000000905970e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 24, false), "1.00000000000000009059697e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 25, false), "1.000000000000000090596966e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 26, false), "1.0000000000000000905969664e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 27, false), "1.00000000000000009059696640e25");
+ assert_eq!(to_string(f, 1.0e25, Minus, 30, false), "1.00000000000000009059696640000e25");
+
+ assert_eq!(to_string(f, 1.0e-6, Minus, 1, false), "1e-6");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 2, false), "1.0e-6");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 16, false), "1.000000000000000e-6");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 17, false), "9.9999999999999995e-7");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 18, false), "9.99999999999999955e-7");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 19, false), "9.999999999999999547e-7");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 20, false), "9.9999999999999995475e-7");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 30, false), "9.99999999999999954748111825886e-7");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 40, false),
+ "9.999999999999999547481118258862586856139e-7");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 50, false),
+ "9.9999999999999995474811182588625868561393872369081e-7");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 60, false),
+ "9.99999999999999954748111825886258685613938723690807819366455e-7");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 70, false),
+ "9.999999999999999547481118258862586856139387236908078193664550781250000e-7");
+
+ assert_eq!(to_string(f, f32::MAX, Minus, 1, false), "3e38");
+ assert_eq!(to_string(f, f32::MAX, Minus, 2, false), "3.4e38");
+ assert_eq!(to_string(f, f32::MAX, Minus, 4, false), "3.403e38");
+ assert_eq!(to_string(f, f32::MAX, Minus, 8, false), "3.4028235e38");
+ assert_eq!(to_string(f, f32::MAX, Minus, 16, false), "3.402823466385289e38");
+ assert_eq!(to_string(f, f32::MAX, Minus, 32, false), "3.4028234663852885981170418348452e38");
+ assert_eq!(to_string(f, f32::MAX, Minus, 64, false),
+ "3.402823466385288598117041834845169254400000000000000000000000000e38");
+
+ let minf32 = ldexp_f32(1.0, -149);
+ assert_eq!(to_string(f, minf32, Minus, 1, false), "1e-45");
+ assert_eq!(to_string(f, minf32, Minus, 2, false), "1.4e-45");
+ assert_eq!(to_string(f, minf32, Minus, 4, false), "1.401e-45");
+ assert_eq!(to_string(f, minf32, Minus, 8, false), "1.4012985e-45");
+ assert_eq!(to_string(f, minf32, Minus, 16, false), "1.401298464324817e-45");
+ assert_eq!(to_string(f, minf32, Minus, 32, false), "1.4012984643248170709237295832899e-45");
+ assert_eq!(to_string(f, minf32, Minus, 64, false),
+ "1.401298464324817070923729583289916131280261941876515771757068284e-45");
+ assert_eq!(to_string(f, minf32, Minus, 128, false),
+ "1.401298464324817070923729583289916131280261941876515771757068283\
+ 8897910826858606014866381883621215820312500000000000000000000000e-45");
+
+ assert_eq!(to_string(f, f64::MAX, Minus, 1, false), "2e308");
+ assert_eq!(to_string(f, f64::MAX, Minus, 2, false), "1.8e308");
+ assert_eq!(to_string(f, f64::MAX, Minus, 4, false), "1.798e308");
+ assert_eq!(to_string(f, f64::MAX, Minus, 8, false), "1.7976931e308");
+ assert_eq!(to_string(f, f64::MAX, Minus, 16, false), "1.797693134862316e308");
+ assert_eq!(to_string(f, f64::MAX, Minus, 32, false), "1.7976931348623157081452742373170e308");
+ assert_eq!(to_string(f, f64::MAX, Minus, 64, false),
+ "1.797693134862315708145274237317043567980705675258449965989174768e308");
+ assert_eq!(to_string(f, f64::MAX, Minus, 128, false),
+ "1.797693134862315708145274237317043567980705675258449965989174768\
+ 0315726078002853876058955863276687817154045895351438246423432133e308");
+ assert_eq!(to_string(f, f64::MAX, Minus, 256, false),
+ "1.797693134862315708145274237317043567980705675258449965989174768\
+ 0315726078002853876058955863276687817154045895351438246423432132\
+ 6889464182768467546703537516986049910576551282076245490090389328\
+ 9440758685084551339423045832369032229481658085593321233482747978e308");
+ assert_eq!(to_string(f, f64::MAX, Minus, 512, false),
+ "1.797693134862315708145274237317043567980705675258449965989174768\
+ 0315726078002853876058955863276687817154045895351438246423432132\
+ 6889464182768467546703537516986049910576551282076245490090389328\
+ 9440758685084551339423045832369032229481658085593321233482747978\
+ 2620414472316873817718091929988125040402618412485836800000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000e308");
+
+ // okay, this is becoming tough. fortunately for us, this is almost the worst case.
+ let minf64 = ldexp_f64(1.0, -1074);
+ assert_eq!(to_string(f, minf64, Minus, 1, false), "5e-324");
+ assert_eq!(to_string(f, minf64, Minus, 2, false), "4.9e-324");
+ assert_eq!(to_string(f, minf64, Minus, 4, false), "4.941e-324");
+ assert_eq!(to_string(f, minf64, Minus, 8, false), "4.9406565e-324");
+ assert_eq!(to_string(f, minf64, Minus, 16, false), "4.940656458412465e-324");
+ assert_eq!(to_string(f, minf64, Minus, 32, false), "4.9406564584124654417656879286822e-324");
+ assert_eq!(to_string(f, minf64, Minus, 64, false),
+ "4.940656458412465441765687928682213723650598026143247644255856825e-324");
+ assert_eq!(to_string(f, minf64, Minus, 128, false),
+ "4.940656458412465441765687928682213723650598026143247644255856825\
+ 0067550727020875186529983636163599237979656469544571773092665671e-324");
+ assert_eq!(to_string(f, minf64, Minus, 256, false),
+ "4.940656458412465441765687928682213723650598026143247644255856825\
+ 0067550727020875186529983636163599237979656469544571773092665671\
+ 0355939796398774796010781878126300713190311404527845817167848982\
+ 1036887186360569987307230500063874091535649843873124733972731696e-324");
+ assert_eq!(to_string(f, minf64, Minus, 512, false),
+ "4.940656458412465441765687928682213723650598026143247644255856825\
+ 0067550727020875186529983636163599237979656469544571773092665671\
+ 0355939796398774796010781878126300713190311404527845817167848982\
+ 1036887186360569987307230500063874091535649843873124733972731696\
+ 1514003171538539807412623856559117102665855668676818703956031062\
+ 4931945271591492455329305456544401127480129709999541931989409080\
+ 4165633245247571478690147267801593552386115501348035264934720193\
+ 7902681071074917033322268447533357208324319360923828934583680601e-324");
+ assert_eq!(to_string(f, minf64, Minus, 1024, false),
+ "4.940656458412465441765687928682213723650598026143247644255856825\
+ 0067550727020875186529983636163599237979656469544571773092665671\
+ 0355939796398774796010781878126300713190311404527845817167848982\
+ 1036887186360569987307230500063874091535649843873124733972731696\
+ 1514003171538539807412623856559117102665855668676818703956031062\
+ 4931945271591492455329305456544401127480129709999541931989409080\
+ 4165633245247571478690147267801593552386115501348035264934720193\
+ 7902681071074917033322268447533357208324319360923828934583680601\
+ 0601150616980975307834227731832924790498252473077637592724787465\
+ 6084778203734469699533647017972677717585125660551199131504891101\
+ 4510378627381672509558373897335989936648099411642057026370902792\
+ 4276754456522908753868250641971826553344726562500000000000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000e-324");
+
+ // very large output
+ assert_eq!(to_string(f, 0.0, Minus, 80000, false), format!("0.{:0>79999}e0", ""));
+ assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), format!("1.{:0>79999}e1", ""));
+ assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), format!("1.{:0>79999}e0", ""));
+ assert_eq!(to_string(f, 1.0e-1, Minus, 80000, false),
+ format!("1.000000000000000055511151231257827021181583404541015625{:0>79945}\
+ e-1", ""));
+ assert_eq!(to_string(f, 1.0e-20, Minus, 80000, false),
+ format!("9.999999999999999451532714542095716517295037027873924471077157760\
+ 66783064379706047475337982177734375{:0>79901}e-21", ""));
+}
+
+pub fn to_exact_fixed_str_test<F>(mut f_: F)
+ where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+ use core::num::flt2dec::Sign::*;
+
+ fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String
+ where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+ to_string_with_parts(|buf, parts| to_exact_fixed_str(|d,b,l| f(d,b,l), v, sign,
+ frac_digits, upper, buf, parts))
+ }
+
+ let f = &mut f_;
+
+ assert_eq!(to_string(f, 0.0, Minus, 0, false), "0");
+ assert_eq!(to_string(f, 0.0, MinusRaw, 0, false), "0");
+ assert_eq!(to_string(f, 0.0, MinusPlus, 0, false), "+0");
+ assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0, false), "+0");
+ assert_eq!(to_string(f, -0.0, Minus, 0, false), "0");
+ assert_eq!(to_string(f, -0.0, MinusRaw, 0, false), "-0");
+ assert_eq!(to_string(f, -0.0, MinusPlus, 0, false), "+0");
+ assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0");
+ assert_eq!(to_string(f, 0.0, Minus, 1, true), "0.0");
+ assert_eq!(to_string(f, 0.0, MinusRaw, 1, true), "0.0");
+ assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0.0");
+ assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, true), "+0.0");
+ assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.00000000");
+ assert_eq!(to_string(f, -0.0, MinusRaw, 8, true), "-0.00000000");
+ assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.00000000");
+ assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, true), "-0.00000000");
+
+ assert_eq!(to_string(f, 1.0/0.0, Minus, 0, false), "inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusRaw, 1, true), "inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusPlus, 8, false), "+inf");
+ assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, 64, true), "+inf");
+ assert_eq!(to_string(f, 0.0/0.0, Minus, 0, false), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusRaw, 1, true), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusPlus, 8, false), "NaN");
+ assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, 64, true), "NaN");
+ assert_eq!(to_string(f, -1.0/0.0, Minus, 0, false), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusRaw, 1, true), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusPlus, 8, false), "-inf");
+ assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64, true), "-inf");
+
+ assert_eq!(to_string(f, 3.14, Minus, 0, false), "3");
+ assert_eq!(to_string(f, 3.14, MinusRaw, 0, false), "3");
+ assert_eq!(to_string(f, 3.14, MinusPlus, 0, false), "+3");
+ assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0, false), "+3");
+ assert_eq!(to_string(f, -3.14, Minus, 0, false), "-3");
+ assert_eq!(to_string(f, -3.14, MinusRaw, 0, false), "-3");
+ assert_eq!(to_string(f, -3.14, MinusPlus, 0, false), "-3");
+ assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3");
+ assert_eq!(to_string(f, 3.14, Minus, 1, true), "3.1");
+ assert_eq!(to_string(f, 3.14, MinusRaw, 2, true), "3.14");
+ assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.140");
+ assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4, true), "+3.1400");
+ assert_eq!(to_string(f, -3.14, Minus, 8, true), "-3.14000000");
+ assert_eq!(to_string(f, -3.14, MinusRaw, 8, true), "-3.14000000");
+ assert_eq!(to_string(f, -3.14, MinusPlus, 8, true), "-3.14000000");
+ assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8, true), "-3.14000000");
+
+ assert_eq!(to_string(f, 0.195, Minus, 0, false), "0");
+ assert_eq!(to_string(f, 0.195, MinusRaw, 0, false), "0");
+ assert_eq!(to_string(f, 0.195, MinusPlus, 0, false), "+0");
+ assert_eq!(to_string(f, 0.195, MinusPlusRaw, 0, false), "+0");
+ assert_eq!(to_string(f, -0.195, Minus, 0, false), "-0");
+ assert_eq!(to_string(f, -0.195, MinusRaw, 0, false), "-0");
+ assert_eq!(to_string(f, -0.195, MinusPlus, 0, false), "-0");
+ assert_eq!(to_string(f, -0.195, MinusPlusRaw, 0, false), "-0");
+ assert_eq!(to_string(f, 0.195, Minus, 1, true), "0.2");
+ assert_eq!(to_string(f, 0.195, MinusRaw, 2, true), "0.20");
+ assert_eq!(to_string(f, 0.195, MinusPlus, 3, true), "+0.195");
+ assert_eq!(to_string(f, 0.195, MinusPlusRaw, 4, true), "+0.1950");
+ assert_eq!(to_string(f, -0.195, Minus, 5, true), "-0.19500");
+ assert_eq!(to_string(f, -0.195, MinusRaw, 6, true), "-0.195000");
+ assert_eq!(to_string(f, -0.195, MinusPlus, 7, true), "-0.1950000");
+ assert_eq!(to_string(f, -0.195, MinusPlusRaw, 8, true), "-0.19500000");
+
+ assert_eq!(to_string(f, 999.5, Minus, 0, false), "1000");
+ assert_eq!(to_string(f, 999.5, Minus, 1, false), "999.5");
+ assert_eq!(to_string(f, 999.5, Minus, 2, false), "999.50");
+ assert_eq!(to_string(f, 999.5, Minus, 3, false), "999.500");
+ assert_eq!(to_string(f, 999.5, Minus, 30, false), "999.500000000000000000000000000000");
+
+ assert_eq!(to_string(f, 0.5, Minus, 0, false), "1");
+ assert_eq!(to_string(f, 0.5, Minus, 1, false), "0.5");
+ assert_eq!(to_string(f, 0.5, Minus, 2, false), "0.50");
+ assert_eq!(to_string(f, 0.5, Minus, 3, false), "0.500");
+
+ assert_eq!(to_string(f, 0.95, Minus, 0, false), "1");
+ assert_eq!(to_string(f, 0.95, Minus, 1, false), "0.9"); // because it really is less than 0.95
+ assert_eq!(to_string(f, 0.95, Minus, 2, false), "0.95");
+ assert_eq!(to_string(f, 0.95, Minus, 3, false), "0.950");
+ assert_eq!(to_string(f, 0.95, Minus, 10, false), "0.9500000000");
+ assert_eq!(to_string(f, 0.95, Minus, 30, false), "0.949999999999999955591079014994");
+
+ assert_eq!(to_string(f, 0.095, Minus, 0, false), "0");
+ assert_eq!(to_string(f, 0.095, Minus, 1, false), "0.1");
+ assert_eq!(to_string(f, 0.095, Minus, 2, false), "0.10");
+ assert_eq!(to_string(f, 0.095, Minus, 3, false), "0.095");
+ assert_eq!(to_string(f, 0.095, Minus, 4, false), "0.0950");
+ assert_eq!(to_string(f, 0.095, Minus, 10, false), "0.0950000000");
+ assert_eq!(to_string(f, 0.095, Minus, 30, false), "0.095000000000000001110223024625");
+
+ assert_eq!(to_string(f, 0.0095, Minus, 0, false), "0");
+ assert_eq!(to_string(f, 0.0095, Minus, 1, false), "0.0");
+ assert_eq!(to_string(f, 0.0095, Minus, 2, false), "0.01");
+ assert_eq!(to_string(f, 0.0095, Minus, 3, false), "0.009"); // really is less than 0.0095
+ assert_eq!(to_string(f, 0.0095, Minus, 4, false), "0.0095");
+ assert_eq!(to_string(f, 0.0095, Minus, 5, false), "0.00950");
+ assert_eq!(to_string(f, 0.0095, Minus, 10, false), "0.0095000000");
+ assert_eq!(to_string(f, 0.0095, Minus, 30, false), "0.009499999999999999764077607267");
+
+ assert_eq!(to_string(f, 7.5e-11, Minus, 0, false), "0");
+ assert_eq!(to_string(f, 7.5e-11, Minus, 3, false), "0.000");
+ assert_eq!(to_string(f, 7.5e-11, Minus, 10, false), "0.0000000001");
+ assert_eq!(to_string(f, 7.5e-11, Minus, 11, false), "0.00000000007"); // ditto
+ assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075");
+ assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750");
+ assert_eq!(to_string(f, 7.5e-11, Minus, 20, false), "0.00000000007500000000");
+ assert_eq!(to_string(f, 7.5e-11, Minus, 30, false), "0.000000000074999999999999999501");
+
+ assert_eq!(to_string(f, 1.0e25, Minus, 0, false), "10000000000000000905969664");
+ assert_eq!(to_string(f, 1.0e25, Minus, 1, false), "10000000000000000905969664.0");
+ assert_eq!(to_string(f, 1.0e25, Minus, 3, false), "10000000000000000905969664.000");
+
+ assert_eq!(to_string(f, 1.0e-6, Minus, 0, false), "0");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 3, false), "0.000");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 6, false), "0.000001");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 9, false), "0.000001000");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 12, false), "0.000001000000");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 22, false), "0.0000010000000000000000");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 23, false), "0.00000099999999999999995");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 24, false), "0.000000999999999999999955");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 25, false), "0.0000009999999999999999547");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 35, false), "0.00000099999999999999995474811182589");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 45, false),
+ "0.000000999999999999999954748111825886258685614");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 55, false),
+ "0.0000009999999999999999547481118258862586856139387236908");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 65, false),
+ "0.00000099999999999999995474811182588625868561393872369080781936646");
+ assert_eq!(to_string(f, 1.0e-6, Minus, 75, false),
+ "0.000000999999999999999954748111825886258685613938723690807819366455078125000");
+
+ assert_eq!(to_string(f, f32::MAX, Minus, 0, false),
+ "340282346638528859811704183484516925440");
+ assert_eq!(to_string(f, f32::MAX, Minus, 1, false),
+ "340282346638528859811704183484516925440.0");
+ assert_eq!(to_string(f, f32::MAX, Minus, 2, false),
+ "340282346638528859811704183484516925440.00");
+
+ let minf32 = ldexp_f32(1.0, -149);
+ assert_eq!(to_string(f, minf32, Minus, 0, false), "0");
+ assert_eq!(to_string(f, minf32, Minus, 1, false), "0.0");
+ assert_eq!(to_string(f, minf32, Minus, 2, false), "0.00");
+ assert_eq!(to_string(f, minf32, Minus, 4, false), "0.0000");
+ assert_eq!(to_string(f, minf32, Minus, 8, false), "0.00000000");
+ assert_eq!(to_string(f, minf32, Minus, 16, false), "0.0000000000000000");
+ assert_eq!(to_string(f, minf32, Minus, 32, false), "0.00000000000000000000000000000000");
+ assert_eq!(to_string(f, minf32, Minus, 64, false),
+ "0.0000000000000000000000000000000000000000000014012984643248170709");
+ assert_eq!(to_string(f, minf32, Minus, 128, false),
+ "0.0000000000000000000000000000000000000000000014012984643248170709\
+ 2372958328991613128026194187651577175706828388979108268586060149");
+ assert_eq!(to_string(f, minf32, Minus, 256, false),
+ "0.0000000000000000000000000000000000000000000014012984643248170709\
+ 2372958328991613128026194187651577175706828388979108268586060148\
+ 6638188362121582031250000000000000000000000000000000000000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000");
+
+ assert_eq!(to_string(f, f64::MAX, Minus, 0, false),
+ "1797693134862315708145274237317043567980705675258449965989174768\
+ 0315726078002853876058955863276687817154045895351438246423432132\
+ 6889464182768467546703537516986049910576551282076245490090389328\
+ 9440758685084551339423045832369032229481658085593321233482747978\
+ 26204144723168738177180919299881250404026184124858368");
+ assert_eq!(to_string(f, f64::MAX, Minus, 10, false),
+ "1797693134862315708145274237317043567980705675258449965989174768\
+ 0315726078002853876058955863276687817154045895351438246423432132\
+ 6889464182768467546703537516986049910576551282076245490090389328\
+ 9440758685084551339423045832369032229481658085593321233482747978\
+ 26204144723168738177180919299881250404026184124858368.0000000000");
+
+ let minf64 = ldexp_f64(1.0, -1074);
+ assert_eq!(to_string(f, minf64, Minus, 0, false), "0");
+ assert_eq!(to_string(f, minf64, Minus, 1, false), "0.0");
+ assert_eq!(to_string(f, minf64, Minus, 10, false), "0.0000000000");
+ assert_eq!(to_string(f, minf64, Minus, 100, false),
+ "0.0000000000000000000000000000000000000000000000000000000000000000\
+ 000000000000000000000000000000000000");
+ assert_eq!(to_string(f, minf64, Minus, 1000, false),
+ "0.0000000000000000000000000000000000000000000000000000000000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000\
+ 0000000000000000000000000000000000000000000000000000000000000000\
+ 0004940656458412465441765687928682213723650598026143247644255856\
+ 8250067550727020875186529983636163599237979656469544571773092665\
+ 6710355939796398774796010781878126300713190311404527845817167848\
+ 9821036887186360569987307230500063874091535649843873124733972731\
+ 6961514003171538539807412623856559117102665855668676818703956031\
+ 0624931945271591492455329305456544401127480129709999541931989409\
+ 0804165633245247571478690147267801593552386115501348035264934720\
+ 1937902681071074917033322268447533357208324319360923828934583680\
+ 6010601150616980975307834227731832924790498252473077637592724787\
+ 4656084778203734469699533647017972677717585125660551199131504891\
+ 1014510378627381672509558373897335989937");
+
+ // very large output
+ assert_eq!(to_string(f, 0.0, Minus, 80000, false), format!("0.{:0>80000}", ""));
+ assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), format!("10.{:0>80000}", ""));
+ assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), format!("1.{:0>80000}", ""));
+ assert_eq!(to_string(f, 1.0e-1, Minus, 80000, false),
+ format!("0.1000000000000000055511151231257827021181583404541015625{:0>79945}", ""));
+ assert_eq!(to_string(f, 1.0e-20, Minus, 80000, false),
+ format!("0.0000000000000000000099999999999999994515327145420957165172950370\
+ 2787392447107715776066783064379706047475337982177734375{:0>79881}", ""));
+}
+
--- /dev/null
+// Copyright 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.
+
+use std::prelude::v1::*;
+use super::super::*;
+use core::num::bignum::Big32x40 as Big;
+use core::num::flt2dec::strategy::dragon::*;
+
+#[test]
+fn test_mul_pow10() {
+ let mut prevpow10 = Big::from_small(1);
+ for i in 1..340 {
+ let mut curpow10 = Big::from_small(1);
+ mul_pow10(&mut curpow10, i);
+ assert_eq!(curpow10, *prevpow10.clone().mul_small(10));
+ prevpow10 = curpow10;
+ }
+}
+
+#[test]
+fn shortest_sanity_test() {
+ f64_shortest_sanity_test(format_shortest);
+ f32_shortest_sanity_test(format_shortest);
+ more_shortest_sanity_test(format_shortest);
+}
+
+#[test]
+fn exact_sanity_test() {
+ // This test ends up running what I can only assume is some corner-ish case
+ // of the `exp2` library function, defined in whatever C runtime we're
+ // using. In VS 2013 this function apparently had a bug as this test fails
+ // when linked, but with VS 2015 the bug appears fixed as the test runs just
+ // fine.
+ //
+ // The bug seems to be a difference in return value of `exp2(-1057)`, where
+ // in VS 2013 it returns a double with the bit pattern 0x2 and in VS 2015 it
+ // returns 0x20000.
+ //
+ // For now just ignore this test entirely on MSVC as it's tested elsewhere
+ // anyway and we're not super interested in testing each platform's exp2
+ // implementation.
+ if !cfg!(target_env = "msvc") {
+ f64_exact_sanity_test(format_exact);
+ }
+ f32_exact_sanity_test(format_exact);
+}
+
+#[test]
+fn test_to_shortest_str() {
+ to_shortest_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_shortest_exp_str() {
+ to_shortest_exp_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_exact_exp_str() {
+ to_exact_exp_str_test(format_exact);
+}
+
+#[test]
+fn test_to_exact_fixed_str() {
+ to_exact_fixed_str_test(format_exact);
+}
+
--- /dev/null
+// Copyright 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.
+
+use std::i16;
+use super::super::*;
+use core::num::flt2dec::strategy::grisu::*;
+
+#[test]
+fn test_cached_power() {
+ assert_eq!(CACHED_POW10.first().unwrap().1, CACHED_POW10_FIRST_E);
+ assert_eq!(CACHED_POW10.last().unwrap().1, CACHED_POW10_LAST_E);
+
+ for e in -1137..961 { // full range for f64
+ let low = ALPHA - e - 64;
+ let high = GAMMA - e - 64;
+ let (_k, cached) = cached_power(low, high);
+ assert!(low <= cached.e && cached.e <= high,
+ "cached_power({}, {}) = {:?} is incorrect", low, high, cached);
+ }
+}
+
+#[test]
+fn test_max_pow10_no_more_than() {
+ let mut prevtenk = 1;
+ for k in 1..10 {
+ let tenk = prevtenk * 10;
+ assert_eq!(max_pow10_no_more_than(tenk - 1), (k - 1, prevtenk));
+ assert_eq!(max_pow10_no_more_than(tenk), (k, tenk));
+ prevtenk = tenk;
+ }
+}
+
+
+#[test]
+fn shortest_sanity_test() {
+ f64_shortest_sanity_test(format_shortest);
+ f32_shortest_sanity_test(format_shortest);
+ more_shortest_sanity_test(format_shortest);
+}
+
+#[test]
+fn shortest_random_equivalence_test() {
+ use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
+ f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000);
+ f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000);
+}
+
+#[test] #[ignore] // it is too expensive
+fn shortest_f32_exhaustive_equivalence_test() {
+ // it is hard to directly test the optimality of the output, but we can at least test if
+ // two different algorithms agree to each other.
+ //
+ // this reports the progress and the number of f32 values returned `None`.
+ // with `--nocapture` (and plenty of time and appropriate rustc flags), this should print:
+ // `done, ignored=17643158 passed=2121451881 failed=0`.
+
+ use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
+ f32_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS);
+}
+
+#[test] #[ignore] // it is too expensive
+fn shortest_f64_hard_random_equivalence_test() {
+ // this again probably has to use appropriate rustc flags.
+
+ use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
+ f64_random_equivalence_test(format_shortest_opt, fallback,
+ MAX_SIG_DIGITS, 100_000_000);
+}
+
+#[test]
+fn exact_sanity_test() {
+ // See comments in dragon.rs's exact_sanity_test for why this test is
+ // ignored on MSVC
+ if !cfg!(target_env = "msvc") {
+ f64_exact_sanity_test(format_exact);
+ }
+ f32_exact_sanity_test(format_exact);
+}
+
+#[test]
+fn exact_f32_random_equivalence_test() {
+ use core::num::flt2dec::strategy::dragon::format_exact as fallback;
+ for k in 1..21 {
+ f32_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN),
+ |d, buf| fallback(d, buf, i16::MIN), k, 1_000);
+ }
+}
+
+#[test]
+fn exact_f64_random_equivalence_test() {
+ use core::num::flt2dec::strategy::dragon::format_exact as fallback;
+ for k in 1..21 {
+ f64_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN),
+ |d, buf| fallback(d, buf, i16::MIN), k, 1_000);
+ }
+}
+
+#[test]
+fn test_to_shortest_str() {
+ to_shortest_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_shortest_exp_str() {
+ to_shortest_exp_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_exact_exp_str() {
+ to_exact_exp_str_test(format_exact);
+}
+
+#[test]
+fn test_to_exact_fixed_str() {
+ to_exact_fixed_str_test(format_exact);
+}
+
--- /dev/null
+// Copyright 2014 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.
+
+int_module!(i16, i16);
--- /dev/null
+// Copyright 2014 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.
+
+int_module!(i32, i32);
--- /dev/null
+// Copyright 2014 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.
+
+int_module!(i64, i64);
--- /dev/null
+// Copyright 2014 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.
+
+int_module!(i8, i8);
--- /dev/null
+// Copyright 2014 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.
+
+macro_rules! int_module { ($T:ident, $T_i:ident) => (
+#[cfg(test)]
+mod tests {
+ use core::$T_i::*;
+ use core::isize;
+ use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr};
+ use core::mem;
+
+ use num;
+
+ #[test]
+ fn test_overflows() {
+ assert!(MAX > 0);
+ assert!(MIN <= 0);
+ assert!(MIN + MAX + 1 == 0);
+ }
+
+ #[test]
+ fn test_num() {
+ num::test_num(10 as $T, 2 as $T);
+ }
+
+ #[test]
+ pub fn test_abs() {
+ assert!((1 as $T).abs() == 1 as $T);
+ assert!((0 as $T).abs() == 0 as $T);
+ assert!((-1 as $T).abs() == 1 as $T);
+ }
+
+ #[test]
+ fn test_signum() {
+ assert!((1 as $T).signum() == 1 as $T);
+ assert!((0 as $T).signum() == 0 as $T);
+ assert!((-0 as $T).signum() == 0 as $T);
+ assert!((-1 as $T).signum() == -1 as $T);
+ }
+
+ #[test]
+ fn test_is_positive() {
+ assert!((1 as $T).is_positive());
+ assert!(!(0 as $T).is_positive());
+ assert!(!(-0 as $T).is_positive());
+ assert!(!(-1 as $T).is_positive());
+ }
+
+ #[test]
+ fn test_is_negative() {
+ assert!(!(1 as $T).is_negative());
+ assert!(!(0 as $T).is_negative());
+ assert!(!(-0 as $T).is_negative());
+ assert!((-1 as $T).is_negative());
+ }
+
+ #[test]
+ fn test_bitwise_operators() {
+ assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
+ assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
+ assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
+ assert!(0b1110 as $T == (0b0111 as $T).shl(1));
+ assert!(0b0111 as $T == (0b1110 as $T).shr(1));
+ assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not());
+ }
+
+ const A: $T = 0b0101100;
+ const B: $T = 0b0100001;
+ const C: $T = 0b1111001;
+
+ const _0: $T = 0;
+ const _1: $T = !0;
+
+ #[test]
+ fn test_count_ones() {
+ assert!(A.count_ones() == 3);
+ assert!(B.count_ones() == 2);
+ assert!(C.count_ones() == 5);
+ }
+
+ #[test]
+ fn test_count_zeros() {
+ let bits = mem::size_of::<$T>() * 8;
+ assert!(A.count_zeros() == bits as u32 - 3);
+ assert!(B.count_zeros() == bits as u32 - 2);
+ assert!(C.count_zeros() == bits as u32 - 5);
+ }
+
+ #[test]
+ fn test_rotate() {
+ assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+ assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+ assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+
+ // Rotating these should make no difference
+ //
+ // We test using 124 bits because to ensure that overlong bit shifts do
+ // not cause undefined behaviour. See #10183.
+ assert_eq!(_0.rotate_left(124), _0);
+ assert_eq!(_1.rotate_left(124), _1);
+ assert_eq!(_0.rotate_right(124), _0);
+ assert_eq!(_1.rotate_right(124), _1);
+
+ // Rotating by 0 should have no effect
+ assert_eq!(A.rotate_left(0), A);
+ assert_eq!(B.rotate_left(0), B);
+ assert_eq!(C.rotate_left(0), C);
+ // Rotating by a multiple of word size should also have no effect
+ assert_eq!(A.rotate_left(64), A);
+ assert_eq!(B.rotate_left(64), B);
+ assert_eq!(C.rotate_left(64), C);
+ }
+
+ #[test]
+ fn test_swap_bytes() {
+ assert_eq!(A.swap_bytes().swap_bytes(), A);
+ assert_eq!(B.swap_bytes().swap_bytes(), B);
+ assert_eq!(C.swap_bytes().swap_bytes(), C);
+
+ // Swapping these should make no difference
+ assert_eq!(_0.swap_bytes(), _0);
+ assert_eq!(_1.swap_bytes(), _1);
+ }
+
+ #[test]
+ fn test_le() {
+ assert_eq!($T::from_le(A.to_le()), A);
+ assert_eq!($T::from_le(B.to_le()), B);
+ assert_eq!($T::from_le(C.to_le()), C);
+ assert_eq!($T::from_le(_0), _0);
+ assert_eq!($T::from_le(_1), _1);
+ assert_eq!(_0.to_le(), _0);
+ assert_eq!(_1.to_le(), _1);
+ }
+
+ #[test]
+ fn test_be() {
+ assert_eq!($T::from_be(A.to_be()), A);
+ assert_eq!($T::from_be(B.to_be()), B);
+ assert_eq!($T::from_be(C.to_be()), C);
+ assert_eq!($T::from_be(_0), _0);
+ assert_eq!($T::from_be(_1), _1);
+ assert_eq!(_0.to_be(), _0);
+ assert_eq!(_1.to_be(), _1);
+ }
+
+ #[test]
+ fn test_signed_checked_div() {
+ assert!((10 as $T).checked_div(2) == Some(5));
+ assert!((5 as $T).checked_div(0) == None);
+ assert!(isize::MIN.checked_div(-1) == None);
+ }
+
+ #[test]
+ fn test_from_str() {
+ fn from_str<T: ::std::str::FromStr>(t: &str) -> Option<T> {
+ ::std::str::FromStr::from_str(t).ok()
+ }
+ assert_eq!(from_str::<$T>("0"), Some(0 as $T));
+ assert_eq!(from_str::<$T>("3"), Some(3 as $T));
+ assert_eq!(from_str::<$T>("10"), Some(10 as $T));
+ assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32));
+ assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
+
+ assert_eq!(from_str::<$T>("-1"), Some(-1 as $T));
+ assert_eq!(from_str::<$T>("-3"), Some(-3 as $T));
+ assert_eq!(from_str::<$T>("-10"), Some(-10 as $T));
+ assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
+ assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));
+
+ assert_eq!(from_str::<$T>(""), None);
+ assert_eq!(from_str::<$T>(" "), None);
+ assert_eq!(from_str::<$T>("x"), None);
+ }
+
+ #[test]
+ fn test_from_str_radix() {
+ assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
+ assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
+ assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
+ assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32));
+ assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
+ assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
+ assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
+ assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T));
+
+ assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T));
+ assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
+ assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T));
+ assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
+ assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
+ assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
+ assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T));
+ assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T));
+
+ assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
+ assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
+ }
+
+ #[test]
+ fn test_pow() {
+ let mut r = 2 as $T;
+
+ assert_eq!(r.pow(2), 4 as $T);
+ assert_eq!(r.pow(0), 1 as $T);
+ r = -2 as $T;
+ assert_eq!(r.pow(2), 4 as $T);
+ assert_eq!(r.pow(3), -8 as $T);
+ }
+}
+
+)}
--- /dev/null
+// Copyright 2014 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.
+
+use core::convert::TryFrom;
+use core::cmp::PartialEq;
+use core::fmt::Debug;
+use core::marker::Copy;
+use core::ops::{Add, Sub, Mul, Div, Rem};
+use core::option::Option;
+use core::option::Option::{Some, None};
+
+#[macro_use]
+mod int_macros;
+
+mod i8;
+mod i16;
+mod i32;
+mod i64;
+
+#[macro_use]
+mod uint_macros;
+
+mod u8;
+mod u16;
+mod u32;
+mod u64;
+
+mod flt2dec;
+mod dec2flt;
+mod bignum;
+
+/// Helper function for testing numeric operations
+pub fn test_num<T>(ten: T, two: T) where
+ T: PartialEq
+ + Add<Output=T> + Sub<Output=T>
+ + Mul<Output=T> + Div<Output=T>
+ + Rem<Output=T> + Debug
+ + Copy
+{
+ assert_eq!(ten.add(two), ten + two);
+ assert_eq!(ten.sub(two), ten - two);
+ assert_eq!(ten.mul(two), ten * two);
+ assert_eq!(ten.div(two), ten / two);
+ assert_eq!(ten.rem(two), ten % two);
+}
+
+#[test]
+fn from_str_issue7588() {
+ let u : Option<u8> = u8::from_str_radix("1000", 10).ok();
+ assert_eq!(u, None);
+ let s : Option<i16> = i16::from_str_radix("80000", 10).ok();
+ assert_eq!(s, None);
+}
+
+#[test]
+fn test_int_from_str_overflow() {
+ let mut i8_val: i8 = 127;
+ assert_eq!("127".parse::<i8>().ok(), Some(i8_val));
+ assert_eq!("128".parse::<i8>().ok(), None);
+
+ i8_val = i8_val.wrapping_add(1);
+ assert_eq!("-128".parse::<i8>().ok(), Some(i8_val));
+ assert_eq!("-129".parse::<i8>().ok(), None);
+
+ let mut i16_val: i16 = 32_767;
+ assert_eq!("32767".parse::<i16>().ok(), Some(i16_val));
+ assert_eq!("32768".parse::<i16>().ok(), None);
+
+ i16_val = i16_val.wrapping_add(1);
+ assert_eq!("-32768".parse::<i16>().ok(), Some(i16_val));
+ assert_eq!("-32769".parse::<i16>().ok(), None);
+
+ let mut i32_val: i32 = 2_147_483_647;
+ assert_eq!("2147483647".parse::<i32>().ok(), Some(i32_val));
+ assert_eq!("2147483648".parse::<i32>().ok(), None);
+
+ i32_val = i32_val.wrapping_add(1);
+ assert_eq!("-2147483648".parse::<i32>().ok(), Some(i32_val));
+ assert_eq!("-2147483649".parse::<i32>().ok(), None);
+
+ let mut i64_val: i64 = 9_223_372_036_854_775_807;
+ assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(i64_val));
+ assert_eq!("9223372036854775808".parse::<i64>().ok(), None);
+
+ i64_val = i64_val.wrapping_add(1);
+ assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(i64_val));
+ assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
+}
+
+#[test]
+fn test_leading_plus() {
+ assert_eq!("+127".parse::<u8>().ok(), Some(127));
+ assert_eq!("+9223372036854775807".parse::<i64>().ok(), Some(9223372036854775807));
+}
+
+#[test]
+fn test_invalid() {
+ assert_eq!("--129".parse::<i8>().ok(), None);
+ assert_eq!("++129".parse::<i8>().ok(), None);
+ assert_eq!("Съешь".parse::<u8>().ok(), None);
+}
+
+#[test]
+fn test_empty() {
+ assert_eq!("-".parse::<i8>().ok(), None);
+ assert_eq!("+".parse::<i8>().ok(), None);
+ assert_eq!("".parse::<u8>().ok(), None);
+}
+
+macro_rules! test_impl_from {
+ ($fn_name: ident, $Small: ty, $Large: ty) => {
+ #[test]
+ fn $fn_name() {
+ let small_max = <$Small>::max_value();
+ let small_min = <$Small>::min_value();
+ let large_max: $Large = small_max.into();
+ let large_min: $Large = small_min.into();
+ assert_eq!(large_max as $Small, small_max);
+ assert_eq!(large_min as $Small, small_min);
+ }
+ }
+}
+
+// Unsigned -> Unsigned
+test_impl_from! { test_u8u16, u8, u16 }
+test_impl_from! { test_u8u32, u8, u32 }
+test_impl_from! { test_u8u64, u8, u64 }
+test_impl_from! { test_u8usize, u8, usize }
+test_impl_from! { test_u16u32, u16, u32 }
+test_impl_from! { test_u16u64, u16, u64 }
+test_impl_from! { test_u32u64, u32, u64 }
+
+// Signed -> Signed
+test_impl_from! { test_i8i16, i8, i16 }
+test_impl_from! { test_i8i32, i8, i32 }
+test_impl_from! { test_i8i64, i8, i64 }
+test_impl_from! { test_i8isize, i8, isize }
+test_impl_from! { test_i16i32, i16, i32 }
+test_impl_from! { test_i16i64, i16, i64 }
+test_impl_from! { test_i32i64, i32, i64 }
+
+// Unsigned -> Signed
+test_impl_from! { test_u8i16, u8, i16 }
+test_impl_from! { test_u8i32, u8, i32 }
+test_impl_from! { test_u8i64, u8, i64 }
+test_impl_from! { test_u16i32, u16, i32 }
+test_impl_from! { test_u16i64, u16, i64 }
+test_impl_from! { test_u32i64, u32, i64 }
+
+// Signed -> Float
+test_impl_from! { test_i8f32, i8, f32 }
+test_impl_from! { test_i8f64, i8, f64 }
+test_impl_from! { test_i16f32, i16, f32 }
+test_impl_from! { test_i16f64, i16, f64 }
+test_impl_from! { test_i32f64, i32, f64 }
+
+// Unsigned -> Float
+test_impl_from! { test_u8f32, u8, f32 }
+test_impl_from! { test_u8f64, u8, f64 }
+test_impl_from! { test_u16f32, u16, f32 }
+test_impl_from! { test_u16f64, u16, f64 }
+test_impl_from! { test_u32f64, u32, f64 }
+
+// Float -> Float
+#[test]
+fn test_f32f64() {
+ use core::f32;
+
+ let max: f64 = f32::MAX.into();
+ assert_eq!(max as f32, f32::MAX);
+ assert!(max.is_normal());
+
+ let min: f64 = f32::MIN.into();
+ assert_eq!(min as f32, f32::MIN);
+ assert!(min.is_normal());
+
+ let min_positive: f64 = f32::MIN_POSITIVE.into();
+ assert_eq!(min_positive as f32, f32::MIN_POSITIVE);
+ assert!(min_positive.is_normal());
+
+ let epsilon: f64 = f32::EPSILON.into();
+ assert_eq!(epsilon as f32, f32::EPSILON);
+ assert!(epsilon.is_normal());
+
+ let zero: f64 = (0.0f32).into();
+ assert_eq!(zero as f32, 0.0f32);
+ assert!(zero.is_sign_positive());
+
+ let neg_zero: f64 = (-0.0f32).into();
+ assert_eq!(neg_zero as f32, -0.0f32);
+ assert!(neg_zero.is_sign_negative());
+
+ let infinity: f64 = f32::INFINITY.into();
+ assert_eq!(infinity as f32, f32::INFINITY);
+ assert!(infinity.is_infinite());
+ assert!(infinity.is_sign_positive());
+
+ let neg_infinity: f64 = f32::NEG_INFINITY.into();
+ assert_eq!(neg_infinity as f32, f32::NEG_INFINITY);
+ assert!(neg_infinity.is_infinite());
+ assert!(neg_infinity.is_sign_negative());
+
+ let nan: f64 = f32::NAN.into();
+ assert!(nan.is_nan());
+}
+
+macro_rules! test_impl_try_from_always_ok {
+ ($fn_name:ident, $source:ty, $target: ty) => {
+ #[test]
+ fn $fn_name() {
+ let max = <$source>::max_value();
+ let min = <$source>::min_value();
+ let zero: $source = 0;
+ assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(),
+ max as $target);
+ assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(),
+ min as $target);
+ assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+ zero as $target);
+ }
+ }
+}
+
+test_impl_try_from_always_ok! { test_try_u8u8, u8, u8 }
+test_impl_try_from_always_ok! { test_try_u8u16, u8, u16 }
+test_impl_try_from_always_ok! { test_try_u8u32, u8, u32 }
+test_impl_try_from_always_ok! { test_try_u8u64, u8, u64 }
+test_impl_try_from_always_ok! { test_try_u8i16, u8, i16 }
+test_impl_try_from_always_ok! { test_try_u8i32, u8, i32 }
+test_impl_try_from_always_ok! { test_try_u8i64, u8, i64 }
+
+test_impl_try_from_always_ok! { test_try_u16u16, u16, u16 }
+test_impl_try_from_always_ok! { test_try_u16u32, u16, u32 }
+test_impl_try_from_always_ok! { test_try_u16u64, u16, u64 }
+test_impl_try_from_always_ok! { test_try_u16i32, u16, i32 }
+test_impl_try_from_always_ok! { test_try_u16i64, u16, i64 }
+
+test_impl_try_from_always_ok! { test_try_u32u32, u32, u32 }
+test_impl_try_from_always_ok! { test_try_u32u64, u32, u64 }
+test_impl_try_from_always_ok! { test_try_u32i64, u32, i64 }
+
+test_impl_try_from_always_ok! { test_try_u64u64, u64, u64 }
+
+test_impl_try_from_always_ok! { test_try_i8i8, i8, i8 }
+test_impl_try_from_always_ok! { test_try_i8i16, i8, i16 }
+test_impl_try_from_always_ok! { test_try_i8i32, i8, i32 }
+test_impl_try_from_always_ok! { test_try_i8i64, i8, i64 }
+
+test_impl_try_from_always_ok! { test_try_i16i16, i16, i16 }
+test_impl_try_from_always_ok! { test_try_i16i32, i16, i32 }
+test_impl_try_from_always_ok! { test_try_i16i64, i16, i64 }
+
+test_impl_try_from_always_ok! { test_try_i32i32, i32, i32 }
+test_impl_try_from_always_ok! { test_try_i32i64, i32, i64 }
+
+test_impl_try_from_always_ok! { test_try_i64i64, i64, i64 }
+
+macro_rules! test_impl_try_from_signed_to_unsigned_upper_ok {
+ ($fn_name:ident, $source:ty, $target:ty) => {
+ #[test]
+ fn $fn_name() {
+ let max = <$source>::max_value();
+ let min = <$source>::min_value();
+ let zero: $source = 0;
+ let neg_one: $source = -1;
+ assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(),
+ max as $target);
+ assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
+ assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+ zero as $target);
+ assert!(<$target as TryFrom<$source>>::try_from(neg_one).is_err());
+ }
+ }
+}
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u8, i8, u8 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u16, i8, u16 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u32, i8, u32 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u64, i8, u64 }
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u16, i16, u16 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u32, i16, u32 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u64, i16, u64 }
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u32, i32, u32 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u64, i32, u64 }
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i64u64, i64, u64 }
+
+macro_rules! test_impl_try_from_unsigned_to_signed_upper_err {
+ ($fn_name:ident, $source:ty, $target:ty) => {
+ #[test]
+ fn $fn_name() {
+ let max = <$source>::max_value();
+ let min = <$source>::min_value();
+ let zero: $source = 0;
+ assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
+ assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(),
+ min as $target);
+ assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+ zero as $target);
+ }
+ }
+}
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u8i8, u8, i8 }
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16i8, u16, i8 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16i16, u16, i16 }
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i8, u32, i8 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i16, u32, i16 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i32, u32, i32 }
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i8, u64, i8 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i16, u64, i16 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i32, u64, i32 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i64, u64, i64 }
+
+macro_rules! test_impl_try_from_same_sign_err {
+ ($fn_name:ident, $source:ty, $target:ty) => {
+ #[test]
+ fn $fn_name() {
+ let max = <$source>::max_value();
+ let min = <$source>::min_value();
+ let zero: $source = 0;
+ let t_max = <$target>::max_value();
+ let t_min = <$target>::min_value();
+ assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
+ if min != 0 {
+ assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
+ }
+ assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+ zero as $target);
+ assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source)
+ .unwrap(),
+ t_max as $target);
+ assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source)
+ .unwrap(),
+ t_min as $target);
+ }
+ }
+}
+
+test_impl_try_from_same_sign_err! { test_try_u16u8, u16, u8 }
+
+test_impl_try_from_same_sign_err! { test_try_u32u8, u32, u8 }
+test_impl_try_from_same_sign_err! { test_try_u32u16, u32, u16 }
+
+test_impl_try_from_same_sign_err! { test_try_u64u8, u64, u8 }
+test_impl_try_from_same_sign_err! { test_try_u64u16, u64, u16 }
+test_impl_try_from_same_sign_err! { test_try_u64u32, u64, u32 }
+
+test_impl_try_from_same_sign_err! { test_try_i16i8, i16, i8 }
+
+test_impl_try_from_same_sign_err! { test_try_i32i8, i32, i8 }
+test_impl_try_from_same_sign_err! { test_try_i32i16, i32, i16 }
+
+test_impl_try_from_same_sign_err! { test_try_i64i8, i64, i8 }
+test_impl_try_from_same_sign_err! { test_try_i64i16, i64, i16 }
+test_impl_try_from_same_sign_err! { test_try_i64i32, i64, i32 }
+
+macro_rules! test_impl_try_from_signed_to_unsigned_err {
+ ($fn_name:ident, $source:ty, $target:ty) => {
+ #[test]
+ fn $fn_name() {
+ let max = <$source>::max_value();
+ let min = <$source>::min_value();
+ let zero: $source = 0;
+ let t_max = <$target>::max_value();
+ let t_min = <$target>::min_value();
+ assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
+ assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
+ assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+ zero as $target);
+ assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source)
+ .unwrap(),
+ t_max as $target);
+ assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source)
+ .unwrap(),
+ t_min as $target);
+ }
+ }
+}
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i16u8, i16, u8 }
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i32u8, i32, u8 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i32u16, i32, u16 }
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u8, i64, u8 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u16, i64, u16 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u32, i64, u32 }
--- /dev/null
+// Copyright 2014 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.
+
+uint_module!(u16, u16);
--- /dev/null
+// Copyright 2014 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.
+
+uint_module!(u32, u32);
--- /dev/null
+// Copyright 2014 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.
+
+uint_module!(u64, u64);
--- /dev/null
+// Copyright 2014 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.
+
+uint_module!(u8, u8);
--- /dev/null
+// Copyright 2014 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.
+
+macro_rules! uint_module { ($T:ident, $T_i:ident) => (
+#[cfg(test)]
+mod tests {
+ use core::$T_i::*;
+ use num;
+ use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not};
+ use std::str::FromStr;
+ use std::mem;
+
+ #[test]
+ fn test_overflows() {
+ assert!(MAX > 0);
+ assert!(MIN <= 0);
+ assert!((MIN + MAX).wrapping_add(1) == 0);
+ }
+
+ #[test]
+ fn test_num() {
+ num::test_num(10 as $T, 2 as $T);
+ }
+
+ #[test]
+ fn test_bitwise_operators() {
+ assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
+ assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
+ assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
+ assert!(0b1110 as $T == (0b0111 as $T).shl(1));
+ assert!(0b0111 as $T == (0b1110 as $T).shr(1));
+ assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not());
+ }
+
+ const A: $T = 0b0101100;
+ const B: $T = 0b0100001;
+ const C: $T = 0b1111001;
+
+ const _0: $T = 0;
+ const _1: $T = !0;
+
+ #[test]
+ fn test_count_ones() {
+ assert!(A.count_ones() == 3);
+ assert!(B.count_ones() == 2);
+ assert!(C.count_ones() == 5);
+ }
+
+ #[test]
+ fn test_count_zeros() {
+ let bits = mem::size_of::<$T>() * 8;
+ assert!(A.count_zeros() == bits as u32 - 3);
+ assert!(B.count_zeros() == bits as u32 - 2);
+ assert!(C.count_zeros() == bits as u32 - 5);
+ }
+
+ #[test]
+ fn test_rotate() {
+ assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+ assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+ assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+
+ // Rotating these should make no difference
+ //
+ // We test using 124 bits because to ensure that overlong bit shifts do
+ // not cause undefined behaviour. See #10183.
+ assert_eq!(_0.rotate_left(124), _0);
+ assert_eq!(_1.rotate_left(124), _1);
+ assert_eq!(_0.rotate_right(124), _0);
+ assert_eq!(_1.rotate_right(124), _1);
+
+ // Rotating by 0 should have no effect
+ assert_eq!(A.rotate_left(0), A);
+ assert_eq!(B.rotate_left(0), B);
+ assert_eq!(C.rotate_left(0), C);
+ // Rotating by a multiple of word size should also have no effect
+ assert_eq!(A.rotate_left(64), A);
+ assert_eq!(B.rotate_left(64), B);
+ assert_eq!(C.rotate_left(64), C);
+ }
+
+ #[test]
+ fn test_swap_bytes() {
+ assert_eq!(A.swap_bytes().swap_bytes(), A);
+ assert_eq!(B.swap_bytes().swap_bytes(), B);
+ assert_eq!(C.swap_bytes().swap_bytes(), C);
+
+ // Swapping these should make no difference
+ assert_eq!(_0.swap_bytes(), _0);
+ assert_eq!(_1.swap_bytes(), _1);
+ }
+
+ #[test]
+ fn test_le() {
+ assert_eq!($T::from_le(A.to_le()), A);
+ assert_eq!($T::from_le(B.to_le()), B);
+ assert_eq!($T::from_le(C.to_le()), C);
+ assert_eq!($T::from_le(_0), _0);
+ assert_eq!($T::from_le(_1), _1);
+ assert_eq!(_0.to_le(), _0);
+ assert_eq!(_1.to_le(), _1);
+ }
+
+ #[test]
+ fn test_be() {
+ assert_eq!($T::from_be(A.to_be()), A);
+ assert_eq!($T::from_be(B.to_be()), B);
+ assert_eq!($T::from_be(C.to_be()), C);
+ assert_eq!($T::from_be(_0), _0);
+ assert_eq!($T::from_be(_1), _1);
+ assert_eq!(_0.to_be(), _0);
+ assert_eq!(_1.to_be(), _1);
+ }
+
+ #[test]
+ fn test_unsigned_checked_div() {
+ assert!((10 as $T).checked_div(2) == Some(5));
+ assert!((5 as $T).checked_div(0) == None);
+ }
+
+ fn from_str<T: FromStr>(t: &str) -> Option<T> {
+ FromStr::from_str(t).ok()
+ }
+
+ #[test]
+ pub fn test_from_str() {
+ assert_eq!(from_str::<$T>("0"), Some(0 as $T));
+ assert_eq!(from_str::<$T>("3"), Some(3 as $T));
+ assert_eq!(from_str::<$T>("10"), Some(10 as $T));
+ assert_eq!(from_str::<u32>("123456789"), Some(123456789 as u32));
+ assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
+
+ assert_eq!(from_str::<$T>(""), None);
+ assert_eq!(from_str::<$T>(" "), None);
+ assert_eq!(from_str::<$T>("x"), None);
+ }
+
+ #[test]
+ pub fn test_parse_bytes() {
+ assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
+ assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
+ assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
+ assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16));
+ assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16));
+ assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
+
+ assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>);
+ assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>);
+ }
+}
+)}
--- /dev/null
+// Copyright 2014 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.
+
+use core::ops::{Range, RangeFull, RangeFrom, RangeTo};
+
+// Test the Range structs without the syntactic sugar.
+
+#[test]
+fn test_range() {
+ let r = Range { start: 2, end: 10 };
+ let mut count = 0;
+ for (i, ri) in r.enumerate() {
+ assert!(ri == i + 2);
+ assert!(ri >= 2 && ri < 10);
+ count += 1;
+ }
+ assert!(count == 8);
+}
+
+#[test]
+fn test_range_from() {
+ let r = RangeFrom { start: 2 };
+ let mut count = 0;
+ for (i, ri) in r.take(10).enumerate() {
+ assert!(ri == i + 2);
+ assert!(ri >= 2 && ri < 12);
+ count += 1;
+ }
+ assert!(count == 10);
+}
+
+#[test]
+fn test_range_to() {
+ // Not much to test.
+ let _ = RangeTo { end: 42 };
+}
+
+#[test]
+fn test_full_range() {
+ // Not much to test.
+ let _ = RangeFull;
+}
--- /dev/null
+// Copyright 2014 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.
+
+use core::option::*;
+use core::mem;
+use core::clone::Clone;
+
+#[test]
+fn test_get_ptr() {
+ unsafe {
+ let x: Box<_> = box 0;
+ let addr_x: *const isize = mem::transmute(&*x);
+ let opt = Some(x);
+ let y = opt.unwrap();
+ let addr_y: *const isize = mem::transmute(&*y);
+ assert_eq!(addr_x, addr_y);
+ }
+}
+
+#[test]
+fn test_get_str() {
+ let x = "test".to_string();
+ let addr_x = x.as_ptr();
+ let opt = Some(x);
+ let y = opt.unwrap();
+ let addr_y = y.as_ptr();
+ assert_eq!(addr_x, addr_y);
+}
+
+#[test]
+fn test_get_resource() {
+ use std::rc::Rc;
+ use core::cell::RefCell;
+
+ struct R {
+ i: Rc<RefCell<isize>>,
+ }
+
+ impl Drop for R {
+ fn drop(&mut self) {
+ let ii = &*self.i;
+ let i = *ii.borrow();
+ *ii.borrow_mut() = i + 1;
+ }
+ }
+
+ fn r(i: Rc<RefCell<isize>>) -> R {
+ R {
+ i: i
+ }
+ }
+
+ let i = Rc::new(RefCell::new(0));
+ {
+ let x = r(i.clone());
+ let opt = Some(x);
+ let _y = opt.unwrap();
+ }
+ assert_eq!(*i.borrow(), 1);
+}
+
+#[test]
+fn test_option_dance() {
+ let x = Some(());
+ let mut y = Some(5);
+ let mut y2 = 0;
+ for _x in x {
+ y2 = y.take().unwrap();
+ }
+ assert_eq!(y2, 5);
+ assert!(y.is_none());
+}
+
+#[test] #[should_panic]
+fn test_option_too_much_dance() {
+ struct A;
+ let mut y = Some(A);
+ let _y2 = y.take().unwrap();
+ let _y3 = y.take().unwrap();
+}
+
+#[test]
+fn test_and() {
+ let x: Option<isize> = Some(1);
+ assert_eq!(x.and(Some(2)), Some(2));
+ assert_eq!(x.and(None::<isize>), None);
+
+ let x: Option<isize> = None;
+ assert_eq!(x.and(Some(2)), None);
+ assert_eq!(x.and(None::<isize>), None);
+}
+
+#[test]
+fn test_and_then() {
+ let x: Option<isize> = Some(1);
+ assert_eq!(x.and_then(|x| Some(x + 1)), Some(2));
+ assert_eq!(x.and_then(|_| None::<isize>), None);
+
+ let x: Option<isize> = None;
+ assert_eq!(x.and_then(|x| Some(x + 1)), None);
+ assert_eq!(x.and_then(|_| None::<isize>), None);
+}
+
+#[test]
+fn test_or() {
+ let x: Option<isize> = Some(1);
+ assert_eq!(x.or(Some(2)), Some(1));
+ assert_eq!(x.or(None), Some(1));
+
+ let x: Option<isize> = None;
+ assert_eq!(x.or(Some(2)), Some(2));
+ assert_eq!(x.or(None), None);
+}
+
+#[test]
+fn test_or_else() {
+ let x: Option<isize> = Some(1);
+ assert_eq!(x.or_else(|| Some(2)), Some(1));
+ assert_eq!(x.or_else(|| None), Some(1));
+
+ let x: Option<isize> = None;
+ assert_eq!(x.or_else(|| Some(2)), Some(2));
+ assert_eq!(x.or_else(|| None), None);
+}
+
+#[test]
+fn test_unwrap() {
+ assert_eq!(Some(1).unwrap(), 1);
+ let s = Some("hello".to_string()).unwrap();
+ assert_eq!(s, "hello");
+}
+
+#[test]
+#[should_panic]
+fn test_unwrap_panic1() {
+ let x: Option<isize> = None;
+ x.unwrap();
+}
+
+#[test]
+#[should_panic]
+fn test_unwrap_panic2() {
+ let x: Option<String> = None;
+ x.unwrap();
+}
+
+#[test]
+fn test_unwrap_or() {
+ let x: Option<isize> = Some(1);
+ assert_eq!(x.unwrap_or(2), 1);
+
+ let x: Option<isize> = None;
+ assert_eq!(x.unwrap_or(2), 2);
+}
+
+#[test]
+fn test_unwrap_or_else() {
+ let x: Option<isize> = Some(1);
+ assert_eq!(x.unwrap_or_else(|| 2), 1);
+
+ let x: Option<isize> = None;
+ assert_eq!(x.unwrap_or_else(|| 2), 2);
+}
+
+#[test]
+fn test_iter() {
+ let val = 5;
+
+ let x = Some(val);
+ let mut it = x.iter();
+
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(it.next(), Some(&val));
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert!(it.next().is_none());
+
+ let mut it = (&x).into_iter();
+ assert_eq!(it.next(), Some(&val));
+}
+
+#[test]
+fn test_mut_iter() {
+ let mut val = 5;
+ let new_val = 11;
+
+ let mut x = Some(val);
+ {
+ let mut it = x.iter_mut();
+
+ assert_eq!(it.size_hint(), (1, Some(1)));
+
+ match it.next() {
+ Some(interior) => {
+ assert_eq!(*interior, val);
+ *interior = new_val;
+ }
+ None => assert!(false),
+ }
+
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert!(it.next().is_none());
+ }
+ assert_eq!(x, Some(new_val));
+
+ let mut y = Some(val);
+ let mut it = (&mut y).into_iter();
+ assert_eq!(it.next(), Some(&mut val));
+}
+
+#[test]
+fn test_ord() {
+ let small = Some(1.0f64);
+ let big = Some(5.0f64);
+ let nan = Some(0.0f64/0.0);
+ assert!(!(nan < big));
+ assert!(!(nan > big));
+ assert!(small < big);
+ assert!(None < big);
+ assert!(big > None);
+}
+
+#[test]
+fn test_collect() {
+ let v: Option<Vec<isize>> = (0..0).map(|_| Some(0)).collect();
+ assert!(v == Some(vec![]));
+
+ let v: Option<Vec<isize>> = (0..3).map(|x| Some(x)).collect();
+ assert!(v == Some(vec![0, 1, 2]));
+
+ let v: Option<Vec<isize>> = (0..3).map(|x| {
+ if x > 1 { None } else { Some(x) }
+ }).collect();
+ assert!(v == None);
+
+ // test that it does not take more elements than it needs
+ let mut functions: [Box<Fn() -> Option<()>>; 3] =
+ [box || Some(()), box || None, box || panic!()];
+
+ let v: Option<Vec<()>> = functions.iter_mut().map(|f| (*f)()).collect();
+
+ assert!(v == None);
+}
+
+
+#[test]
+fn test_cloned() {
+ let val = 1;
+ let val_ref = &val;
+ let opt_none: Option<&'static u32> = None;
+ let opt_ref = Some(&val);
+ let opt_ref_ref = Some(&val_ref);
+
+ // None works
+ assert_eq!(opt_none.clone(), None);
+ assert_eq!(opt_none.cloned(), None);
+
+ // Immutable ref works
+ assert_eq!(opt_ref.clone(), Some(&val));
+ assert_eq!(opt_ref.cloned(), Some(1));
+
+ // Double Immutable ref works
+ assert_eq!(opt_ref_ref.clone(), Some(&val_ref));
+ assert_eq!(opt_ref_ref.clone().cloned(), Some(&val));
+ assert_eq!(opt_ref_ref.cloned().cloned(), Some(1));
+}
--- /dev/null
+// Copyright 2014 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.
+
+use core::ptr::*;
+use core::cell::RefCell;
+
+#[test]
+fn test() {
+ unsafe {
+ struct Pair {
+ fst: isize,
+ snd: isize
+ };
+ let mut p = Pair {fst: 10, snd: 20};
+ let pptr: *mut Pair = &mut p;
+ let iptr: *mut isize = pptr as *mut isize;
+ assert_eq!(*iptr, 10);
+ *iptr = 30;
+ assert_eq!(*iptr, 30);
+ assert_eq!(p.fst, 30);
+
+ *pptr = Pair {fst: 50, snd: 60};
+ assert_eq!(*iptr, 50);
+ assert_eq!(p.fst, 50);
+ assert_eq!(p.snd, 60);
+
+ let v0 = vec![32000u16, 32001u16, 32002u16];
+ let mut v1 = vec![0u16, 0u16, 0u16];
+
+ copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
+ assert!((v1[0] == 0u16 &&
+ v1[1] == 32001u16 &&
+ v1[2] == 0u16));
+ copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
+ assert!((v1[0] == 32002u16 &&
+ v1[1] == 32001u16 &&
+ v1[2] == 0u16));
+ copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
+ assert!((v1[0] == 32002u16 &&
+ v1[1] == 32001u16 &&
+ v1[2] == 32000u16));
+ }
+}
+
+#[test]
+fn test_is_null() {
+ let p: *const isize = null();
+ assert!(p.is_null());
+
+ let q = unsafe { p.offset(1) };
+ assert!(!q.is_null());
+
+ let mp: *mut isize = null_mut();
+ assert!(mp.is_null());
+
+ let mq = unsafe { mp.offset(1) };
+ assert!(!mq.is_null());
+}
+
+#[test]
+fn test_as_ref() {
+ unsafe {
+ let p: *const isize = null();
+ assert_eq!(p.as_ref(), None);
+
+ let q: *const isize = &2;
+ assert_eq!(q.as_ref().unwrap(), &2);
+
+ let p: *mut isize = null_mut();
+ assert_eq!(p.as_ref(), None);
+
+ let q: *mut isize = &mut 2;
+ assert_eq!(q.as_ref().unwrap(), &2);
+
+ // Lifetime inference
+ let u = 2isize;
+ {
+ let p = &u as *const isize;
+ assert_eq!(p.as_ref().unwrap(), &2);
+ }
+ }
+}
+
+#[test]
+fn test_as_mut() {
+ unsafe {
+ let p: *mut isize = null_mut();
+ assert!(p.as_mut() == None);
+
+ let q: *mut isize = &mut 2;
+ assert!(q.as_mut().unwrap() == &mut 2);
+
+ // Lifetime inference
+ let mut u = 2isize;
+ {
+ let p = &mut u as *mut isize;
+ assert!(p.as_mut().unwrap() == &mut 2);
+ }
+ }
+}
+
+#[test]
+fn test_ptr_addition() {
+ unsafe {
+ let xs = vec![5; 16];
+ let mut ptr = xs.as_ptr();
+ let end = ptr.offset(16);
+
+ while ptr < end {
+ assert_eq!(*ptr, 5);
+ ptr = ptr.offset(1);
+ }
+
+ let mut xs_mut = xs;
+ let mut m_ptr = xs_mut.as_mut_ptr();
+ let m_end = m_ptr.offset(16);
+
+ while m_ptr < m_end {
+ *m_ptr += 5;
+ m_ptr = m_ptr.offset(1);
+ }
+
+ assert!(xs_mut == vec![10; 16]);
+ }
+}
+
+#[test]
+fn test_ptr_subtraction() {
+ unsafe {
+ let xs = vec![0,1,2,3,4,5,6,7,8,9];
+ let mut idx = 9;
+ let ptr = xs.as_ptr();
+
+ while idx >= 0 {
+ assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
+ idx = idx - 1;
+ }
+
+ let mut xs_mut = xs;
+ let m_start = xs_mut.as_mut_ptr();
+ let mut m_ptr = m_start.offset(9);
+
+ while m_ptr >= m_start {
+ *m_ptr += *m_ptr;
+ m_ptr = m_ptr.offset(-1);
+ }
+
+ assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
+ }
+}
+
+#[test]
+fn test_set_memory() {
+ let mut xs = [0u8; 20];
+ let ptr = xs.as_mut_ptr();
+ unsafe { write_bytes(ptr, 5u8, xs.len()); }
+ assert!(xs == [5u8; 20]);
+}
+
+#[test]
+fn test_unsized_unique() {
+ let xs: &mut [i32] = &mut [1, 2, 3];
+ let ptr = unsafe { Unique::new(xs as *mut [i32]) };
+ let ys = unsafe { &mut **ptr };
+ let zs: &mut [i32] = &mut [1, 2, 3];
+ assert!(ys == zs);
+}
+
+#[test]
+#[allow(warnings)]
+// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
+// ABI, or even point to an actual executable code, because the function itself is never invoked.
+#[no_mangle]
+pub fn test_variadic_fnptr() {
+ use core::hash::{Hash, SipHasher};
+ extern {
+ fn test_variadic_fnptr(_: u64, ...) -> f64;
+ }
+ let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
+ let q = p.clone();
+ assert_eq!(p, q);
+ assert!(!(p < q));
+ let mut s = SipHasher::new();
+ assert_eq!(p.hash(&mut s), q.hash(&mut s));
+}
+
+#[test]
+fn write_unaligned_drop() {
+ thread_local! {
+ static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
+ }
+
+ struct Dropper(u32);
+
+ impl Drop for Dropper {
+ fn drop(&mut self) {
+ DROPS.with(|d| d.borrow_mut().push(self.0));
+ }
+ }
+
+ {
+ let c = Dropper(0);
+ let mut t = Dropper(1);
+ unsafe { write_unaligned(&mut t, c); }
+ }
+ DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
+}
--- /dev/null
+// Copyright 2014 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.
+
+fn op1() -> Result<isize, &'static str> { Ok(666) }
+fn op2() -> Result<isize, &'static str> { Err("sadface") }
+
+#[test]
+fn test_and() {
+ assert_eq!(op1().and(Ok(667)).unwrap(), 667);
+ assert_eq!(op1().and(Err::<i32, &'static str>("bad")).unwrap_err(),
+ "bad");
+
+ assert_eq!(op2().and(Ok(667)).unwrap_err(), "sadface");
+ assert_eq!(op2().and(Err::<i32,&'static str>("bad")).unwrap_err(),
+ "sadface");
+}
+
+#[test]
+fn test_and_then() {
+ assert_eq!(op1().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap(), 667);
+ assert_eq!(op1().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
+ "bad");
+
+ assert_eq!(op2().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap_err(),
+ "sadface");
+ assert_eq!(op2().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
+ "sadface");
+}
+
+#[test]
+fn test_or() {
+ assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666);
+ assert_eq!(op1().or(Err("bad")).unwrap(), 666);
+
+ assert_eq!(op2().or(Ok::<_, &'static str>(667)).unwrap(), 667);
+ assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad");
+}
+
+#[test]
+fn test_or_else() {
+ assert_eq!(op1().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 666);
+ assert_eq!(op1().or_else(|e| Err::<isize, &'static str>(e)).unwrap(), 666);
+
+ assert_eq!(op2().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 667);
+ assert_eq!(op2().or_else(|e| Err::<isize, &'static str>(e)).unwrap_err(),
+ "sadface");
+}
+
+#[test]
+fn test_impl_map() {
+ assert!(Ok::<isize, isize>(1).map(|x| x + 1) == Ok(2));
+ assert!(Err::<isize, isize>(1).map(|x| x + 1) == Err(1));
+}
+
+#[test]
+fn test_impl_map_err() {
+ assert!(Ok::<isize, isize>(1).map_err(|x| x + 1) == Ok(1));
+ assert!(Err::<isize, isize>(1).map_err(|x| x + 1) == Err(2));
+}
+
+#[test]
+fn test_collect() {
+ let v: Result<Vec<isize>, ()> = (0..0).map(|_| Ok::<isize, ()>(0)).collect();
+ assert!(v == Ok(vec![]));
+
+ let v: Result<Vec<isize>, ()> = (0..3).map(|x| Ok::<isize, ()>(x)).collect();
+ assert!(v == Ok(vec![0, 1, 2]));
+
+ let v: Result<Vec<isize>, isize> = (0..3).map(|x| {
+ if x > 1 { Err(x) } else { Ok(x) }
+ }).collect();
+ assert!(v == Err(2));
+
+ // test that it does not take more elements than it needs
+ let mut functions: [Box<Fn() -> Result<(), isize>>; 3] =
+ [box || Ok(()), box || Err(1), box || panic!()];
+
+ let v: Result<Vec<()>, isize> = functions.iter_mut().map(|f| (*f)()).collect();
+ assert!(v == Err(1));
+}
+
+#[test]
+fn test_fmt_default() {
+ let ok: Result<isize, &'static str> = Ok(100);
+ let err: Result<isize, &'static str> = Err("Err");
+
+ let s = format!("{:?}", ok);
+ assert_eq!(s, "Ok(100)");
+ let s = format!("{:?}", err);
+ assert_eq!(s, "Err(\"Err\")");
+}
+
+#[test]
+fn test_unwrap_or() {
+ let ok: Result<isize, &'static str> = Ok(100);
+ let ok_err: Result<isize, &'static str> = Err("Err");
+
+ assert_eq!(ok.unwrap_or(50), 100);
+ assert_eq!(ok_err.unwrap_or(50), 50);
+}
+
+#[test]
+fn test_unwrap_or_else() {
+ fn handler(msg: &'static str) -> isize {
+ if msg == "I got this." {
+ 50
+ } else {
+ panic!("BadBad")
+ }
+ }
+
+ let ok: Result<isize, &'static str> = Ok(100);
+ let ok_err: Result<isize, &'static str> = Err("I got this.");
+
+ assert_eq!(ok.unwrap_or_else(handler), 100);
+ assert_eq!(ok_err.unwrap_or_else(handler), 50);
+}
+
+#[test]
+#[should_panic]
+pub fn test_unwrap_or_else_panic() {
+ fn handler(msg: &'static str) -> isize {
+ if msg == "I got this." {
+ 50
+ } else {
+ panic!("BadBad")
+ }
+ }
+
+ let bad_err: Result<isize, &'static str> = Err("Unrecoverable mess.");
+ let _ : isize = bad_err.unwrap_or_else(handler);
+}
+
+
+#[test]
+pub fn test_expect_ok() {
+ let ok: Result<isize, &'static str> = Ok(100);
+ assert_eq!(ok.expect("Unexpected error"), 100);
+}
+#[test]
+#[should_panic(expected="Got expected error: \"All good\"")]
+pub fn test_expect_err() {
+ let err: Result<isize, &'static str> = Err("All good");
+ err.expect("Got expected error");
+}
+
+
+#[test]
+pub fn test_expect_err_err() {
+ let ok: Result<&'static str, isize> = Err(100);
+ assert_eq!(ok.expect_err("Unexpected ok"), 100);
+}
+#[test]
+#[should_panic(expected="Got expected ok: \"All good\"")]
+pub fn test_expect_err_ok() {
+ let err: Result<&'static str, isize> = Ok("All good");
+ err.expect_err("Got expected ok");
+}
+
+#[test]
+pub fn test_iter() {
+ let ok: Result<isize, &'static str> = Ok(100);
+ let mut it = ok.iter();
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(it.next(), Some(&100));
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert!(it.next().is_none());
+ assert_eq!((&ok).into_iter().next(), Some(&100));
+
+ let err: Result<isize, &'static str> = Err("error");
+ assert_eq!(err.iter().next(), None);
+}
+
+#[test]
+pub fn test_iter_mut() {
+ let mut ok: Result<isize, &'static str> = Ok(100);
+ for loc in ok.iter_mut() {
+ *loc = 200;
+ }
+ assert_eq!(ok, Ok(200));
+ for loc in &mut ok {
+ *loc = 300;
+ }
+ assert_eq!(ok, Ok(300));
+
+ let mut err: Result<isize, &'static str> = Err("error");
+ for loc in err.iter_mut() {
+ *loc = 200;
+ }
+ assert_eq!(err, Err("error"));
+}
+
+#[test]
+pub fn test_unwrap_or_default() {
+ assert_eq!(op1().unwrap_or_default(), 666);
+ assert_eq!(op2().unwrap_or_default(), 0);
+}
--- /dev/null
+// Copyright 2014 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.
+
+use core::cmp::Ordering::{Equal, Greater, Less};
+use core::slice::heapsort;
+use core::result::Result::{Ok, Err};
+use rand::{Rng, XorShiftRng};
+
+#[test]
+fn test_binary_search() {
+ let b = [1, 2, 4, 6, 8, 9];
+ assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
+ assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
+ let b = [1, 2, 4, 6, 7, 8, 9];
+ assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
+ assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
+ let b = [1, 2, 4, 6, 8, 9];
+ assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(4));
+ assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(4));
+ let b = [1, 2, 4, 6, 7, 8, 9];
+ assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(5));
+ let b = [1, 2, 4, 5, 6, 8, 9];
+ assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(5));
+ assert!(b.binary_search_by(|v| v.cmp(&0)) == Err(0));
+ let b = [1, 2, 4, 5, 6, 8];
+ assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6));
+}
+
+#[test]
+fn test_iterator_nth() {
+ let v: &[_] = &[0, 1, 2, 3, 4];
+ for i in 0..v.len() {
+ assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
+ }
+ assert_eq!(v.iter().nth(v.len()), None);
+
+ let mut iter = v.iter();
+ assert_eq!(iter.nth(2).unwrap(), &v[2]);
+ assert_eq!(iter.nth(1).unwrap(), &v[4]);
+}
+
+#[test]
+fn test_iterator_last() {
+ let v: &[_] = &[0, 1, 2, 3, 4];
+ assert_eq!(v.iter().last().unwrap(), &4);
+ assert_eq!(v[..1].iter().last().unwrap(), &0);
+}
+
+#[test]
+fn test_iterator_count() {
+ let v: &[_] = &[0, 1, 2, 3, 4];
+ assert_eq!(v.iter().count(), 5);
+
+ let mut iter2 = v.iter();
+ iter2.next();
+ iter2.next();
+ assert_eq!(iter2.count(), 3);
+}
+
+#[test]
+fn test_chunks_count() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let c = v.chunks(3);
+ assert_eq!(c.count(), 2);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let c2 = v2.chunks(2);
+ assert_eq!(c2.count(), 3);
+
+ let v3: &[i32] = &[];
+ let c3 = v3.chunks(2);
+ assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_chunks_nth() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let mut c = v.chunks(2);
+ assert_eq!(c.nth(1).unwrap()[1], 3);
+ assert_eq!(c.next().unwrap()[0], 4);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let mut c2 = v2.chunks(3);
+ assert_eq!(c2.nth(1).unwrap()[1], 4);
+ assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_chunks_last() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let c = v.chunks(2);
+ assert_eq!(c.last().unwrap()[1], 5);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let c2 = v2.chunks(2);
+ assert_eq!(c2.last().unwrap()[0], 4);
+}
+
+#[test]
+fn test_chunks_mut_count() {
+ let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ let c = v.chunks_mut(3);
+ assert_eq!(c.count(), 2);
+
+ let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+ let c2 = v2.chunks_mut(2);
+ assert_eq!(c2.count(), 3);
+
+ let mut v3: &mut [i32] = &mut [];
+ let c3 = v3.chunks_mut(2);
+ assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_chunks_mut_nth() {
+ let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ let mut c = v.chunks_mut(2);
+ assert_eq!(c.nth(1).unwrap()[1], 3);
+ assert_eq!(c.next().unwrap()[0], 4);
+
+ let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+ let mut c2 = v2.chunks_mut(3);
+ assert_eq!(c2.nth(1).unwrap()[1], 4);
+ assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_chunks_mut_last() {
+ let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ let c = v.chunks_mut(2);
+ assert_eq!(c.last().unwrap()[1], 5);
+
+ let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+ let c2 = v2.chunks_mut(2);
+ assert_eq!(c2.last().unwrap()[0], 4);
+}
+
+#[test]
+fn test_windows_count() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let c = v.windows(3);
+ assert_eq!(c.count(), 4);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let c2 = v2.windows(6);
+ assert_eq!(c2.count(), 0);
+
+ let v3: &[i32] = &[];
+ let c3 = v3.windows(2);
+ assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_windows_nth() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let mut c = v.windows(2);
+ assert_eq!(c.nth(2).unwrap()[1], 3);
+ assert_eq!(c.next().unwrap()[0], 3);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let mut c2 = v2.windows(4);
+ assert_eq!(c2.nth(1).unwrap()[1], 2);
+ assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_windows_last() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let c = v.windows(2);
+ assert_eq!(c.last().unwrap()[1], 5);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let c2 = v2.windows(2);
+ assert_eq!(c2.last().unwrap()[0], 3);
+}
+
+#[test]
+fn get_range() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ assert_eq!(v.get(..), Some(&[0, 1, 2, 3, 4, 5][..]));
+ assert_eq!(v.get(..2), Some(&[0, 1][..]));
+ assert_eq!(v.get(2..), Some(&[2, 3, 4, 5][..]));
+ assert_eq!(v.get(1..4), Some(&[1, 2, 3][..]));
+ assert_eq!(v.get(7..), None);
+ assert_eq!(v.get(7..10), None);
+}
+
+#[test]
+fn get_mut_range() {
+ let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ assert_eq!(v.get_mut(..), Some(&mut [0, 1, 2, 3, 4, 5][..]));
+ assert_eq!(v.get_mut(..2), Some(&mut [0, 1][..]));
+ assert_eq!(v.get_mut(2..), Some(&mut [2, 3, 4, 5][..]));
+ assert_eq!(v.get_mut(1..4), Some(&mut [1, 2, 3][..]));
+ assert_eq!(v.get_mut(7..), None);
+ assert_eq!(v.get_mut(7..10), None);
+}
+
+#[test]
+fn get_unchecked_range() {
+ unsafe {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ assert_eq!(v.get_unchecked(..), &[0, 1, 2, 3, 4, 5][..]);
+ assert_eq!(v.get_unchecked(..2), &[0, 1][..]);
+ assert_eq!(v.get_unchecked(2..), &[2, 3, 4, 5][..]);
+ assert_eq!(v.get_unchecked(1..4), &[1, 2, 3][..]);
+ }
+}
+
+#[test]
+fn get_unchecked_mut_range() {
+ unsafe {
+ let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ assert_eq!(v.get_unchecked_mut(..), &mut [0, 1, 2, 3, 4, 5][..]);
+ assert_eq!(v.get_unchecked_mut(..2), &mut [0, 1][..]);
+ assert_eq!(v.get_unchecked_mut(2..), &mut[2, 3, 4, 5][..]);
+ assert_eq!(v.get_unchecked_mut(1..4), &mut [1, 2, 3][..]);
+ }
+}
+
+#[test]
+fn sort_unstable() {
+ let mut v = [0; 600];
+ let mut tmp = [0; 600];
+ let mut rng = XorShiftRng::new_unseeded();
+
+ for len in (2..25).chain(500..510) {
+ let v = &mut v[0..len];
+ let tmp = &mut tmp[0..len];
+
+ for &modulus in &[5, 10, 100, 1000] {
+ for _ in 0..100 {
+ for i in 0..len {
+ v[i] = rng.gen::<i32>() % modulus;
+ }
+
+ // Sort in default order.
+ tmp.copy_from_slice(v);
+ tmp.sort_unstable();
+ assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
+
+ // Sort in ascending order.
+ tmp.copy_from_slice(v);
+ tmp.sort_unstable_by(|a, b| a.cmp(b));
+ assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
+
+ // Sort in descending order.
+ tmp.copy_from_slice(v);
+ tmp.sort_unstable_by(|a, b| b.cmp(a));
+ assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
+
+ // Test heapsort using `<` operator.
+ tmp.copy_from_slice(v);
+ heapsort(tmp, |a, b| a < b);
+ assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
+
+ // Test heapsort using `>` operator.
+ tmp.copy_from_slice(v);
+ heapsort(tmp, |a, b| a > b);
+ assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
+ }
+ }
+ }
+
+ // Sort using a completely random comparison function.
+ // This will reorder the elements *somehow*, but won't panic.
+ for i in 0..v.len() {
+ v[i] = i as i32;
+ }
+ v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap());
+ v.sort_unstable();
+ for i in 0..v.len() {
+ assert_eq!(v[i], i as i32);
+ }
+
+ // Should not panic.
+ [0i32; 0].sort_unstable();
+ [(); 10].sort_unstable();
+ [(); 100].sort_unstable();
+
+ let mut v = [0xDEADBEEFu64];
+ v.sort_unstable();
+ assert!(v == [0xDEADBEEF]);
+}
--- /dev/null
+// Copyright 2014-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.
+
+// All `str` tests live in collectionstests::str
--- /dev/null
+// Copyright 2014 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.
+
+use std::cmp::Ordering::{Equal, Less, Greater};
+
+#[test]
+fn test_clone() {
+ let a = (1, "2");
+ let b = a.clone();
+ assert_eq!(a, b);
+}
+
+#[test]
+fn test_tuple_cmp() {
+ let (small, big) = ((1, 2, 3), (3, 2, 1));
+
+ let nan = 0.0f64/0.0;
+
+ // PartialEq
+ assert_eq!(small, small);
+ assert_eq!(big, big);
+ assert!(small != big);
+ assert!(big != small);
+
+ // PartialOrd
+ assert!(small < big);
+ assert!(!(small < small));
+ assert!(!(big < small));
+ assert!(!(big < big));
+
+ assert!(small <= small);
+ assert!(big <= big);
+
+ assert!(big > small);
+ assert!(small >= small);
+ assert!(big >= small);
+ assert!(big >= big);
+
+ assert!(!((1.0f64, 2.0f64) < (nan, 3.0)));
+ assert!(!((1.0f64, 2.0f64) <= (nan, 3.0)));
+ assert!(!((1.0f64, 2.0f64) > (nan, 3.0)));
+ assert!(!((1.0f64, 2.0f64) >= (nan, 3.0)));
+ assert!(((1.0f64, 2.0f64) < (2.0, nan)));
+ assert!(!((2.0f64, 2.0f64) < (2.0, nan)));
+
+ // Ord
+ assert!(small.cmp(&small) == Equal);
+ assert!(big.cmp(&big) == Equal);
+ assert!(small.cmp(&big) == Less);
+ assert!(big.cmp(&small) == Greater);
+}
+
+#[test]
+fn test_show() {
+ let s = format!("{:?}", (1,));
+ assert_eq!(s, "(1,)");
+ let s = format!("{:?}", (1, true));
+ assert_eq!(s, "(1, true)");
+ let s = format!("{:?}", (1, "hi", true));
+ assert_eq!(s, "(1, \"hi\", true)");
+}
+++ /dev/null
-// Copyright 2014 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.
-
-use core::any::*;
-
-#[derive(PartialEq, Debug)]
-struct Test;
-
-static TEST: &'static str = "Test";
-
-#[test]
-fn any_referenced() {
- let (a, b, c) = (&5 as &Any, &TEST as &Any, &Test as &Any);
-
- assert!(a.is::<i32>());
- assert!(!b.is::<i32>());
- assert!(!c.is::<i32>());
-
- assert!(!a.is::<&'static str>());
- assert!(b.is::<&'static str>());
- assert!(!c.is::<&'static str>());
-
- assert!(!a.is::<Test>());
- assert!(!b.is::<Test>());
- assert!(c.is::<Test>());
-}
-
-#[test]
-fn any_owning() {
- let (a, b, c) = (box 5_usize as Box<Any>, box TEST as Box<Any>, box Test as Box<Any>);
-
- assert!(a.is::<usize>());
- assert!(!b.is::<usize>());
- assert!(!c.is::<usize>());
-
- assert!(!a.is::<&'static str>());
- assert!(b.is::<&'static str>());
- assert!(!c.is::<&'static str>());
-
- assert!(!a.is::<Test>());
- assert!(!b.is::<Test>());
- assert!(c.is::<Test>());
-}
-
-#[test]
-fn any_downcast_ref() {
- let a = &5_usize as &Any;
-
- match a.downcast_ref::<usize>() {
- Some(&5) => {}
- x => panic!("Unexpected value {:?}", x)
- }
-
- match a.downcast_ref::<Test>() {
- None => {}
- x => panic!("Unexpected value {:?}", x)
- }
-}
-
-#[test]
-fn any_downcast_mut() {
- let mut a = 5_usize;
- let mut b: Box<_> = box 7_usize;
-
- let a_r = &mut a as &mut Any;
- let tmp: &mut usize = &mut *b;
- let b_r = tmp as &mut Any;
-
- match a_r.downcast_mut::<usize>() {
- Some(x) => {
- assert_eq!(*x, 5);
- *x = 612;
- }
- x => panic!("Unexpected value {:?}", x)
- }
-
- match b_r.downcast_mut::<usize>() {
- Some(x) => {
- assert_eq!(*x, 7);
- *x = 413;
- }
- x => panic!("Unexpected value {:?}", x)
- }
-
- match a_r.downcast_mut::<Test>() {
- None => (),
- x => panic!("Unexpected value {:?}", x)
- }
-
- match b_r.downcast_mut::<Test>() {
- None => (),
- x => panic!("Unexpected value {:?}", x)
- }
-
- match a_r.downcast_mut::<usize>() {
- Some(&mut 612) => {}
- x => panic!("Unexpected value {:?}", x)
- }
-
- match b_r.downcast_mut::<usize>() {
- Some(&mut 413) => {}
- x => panic!("Unexpected value {:?}", x)
- }
-}
-
-#[test]
-fn any_fixed_vec() {
- let test = [0_usize; 8];
- let test = &test as &Any;
- assert!(test.is::<[usize; 8]>());
- assert!(!test.is::<[usize; 10]>());
-}
-
-#[test]
-fn any_unsized() {
- fn is_any<T: Any + ?Sized>() {}
- is_any::<[i32]>();
-}
+++ /dev/null
-// Copyright 2014 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.
-use core::array::FixedSizeArray;
-
-#[test]
-fn fixed_size_array() {
- let mut array = [0; 64];
- let mut zero_sized = [(); 64];
- let mut empty_array = [0; 0];
- let mut empty_zero_sized = [(); 0];
-
- assert_eq!(FixedSizeArray::as_slice(&array).len(), 64);
- assert_eq!(FixedSizeArray::as_slice(&zero_sized).len(), 64);
- assert_eq!(FixedSizeArray::as_slice(&empty_array).len(), 0);
- assert_eq!(FixedSizeArray::as_slice(&empty_zero_sized).len(), 0);
-
- assert_eq!(FixedSizeArray::as_mut_slice(&mut array).len(), 64);
- assert_eq!(FixedSizeArray::as_mut_slice(&mut zero_sized).len(), 64);
- assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0);
- assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0);
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use core::sync::atomic::*;
-use core::sync::atomic::Ordering::SeqCst;
-
-#[test]
-fn bool_() {
- let a = AtomicBool::new(false);
- assert_eq!(a.compare_and_swap(false, true, SeqCst), false);
- assert_eq!(a.compare_and_swap(false, true, SeqCst), true);
-
- a.store(false, SeqCst);
- assert_eq!(a.compare_and_swap(false, true, SeqCst), false);
-}
-
-#[test]
-fn bool_and() {
- let a = AtomicBool::new(true);
- assert_eq!(a.fetch_and(false, SeqCst),true);
- assert_eq!(a.load(SeqCst),false);
-}
-
-#[test]
-fn uint_and() {
- let x = AtomicUsize::new(0xf731);
- assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
- assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
-}
-
-#[test]
-fn uint_or() {
- let x = AtomicUsize::new(0xf731);
- assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
- assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
-}
-
-#[test]
-fn uint_xor() {
- let x = AtomicUsize::new(0xf731);
- assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
- assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
-}
-
-#[test]
-fn int_and() {
- let x = AtomicIsize::new(0xf731);
- assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
- assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
-}
-
-#[test]
-fn int_or() {
- let x = AtomicIsize::new(0xf731);
- assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
- assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
-}
-
-#[test]
-fn int_xor() {
- let x = AtomicIsize::new(0xf731);
- assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
- assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
-}
-
-static S_FALSE: AtomicBool = AtomicBool::new(false);
-static S_TRUE: AtomicBool = AtomicBool::new(true);
-static S_INT: AtomicIsize = AtomicIsize::new(0);
-static S_UINT: AtomicUsize = AtomicUsize::new(0);
-
-#[test]
-fn static_init() {
- assert!(!S_FALSE.load(SeqCst));
- assert!(S_TRUE.load(SeqCst));
- assert!(S_INT.load(SeqCst) == 0);
- assert!(S_UINT.load(SeqCst) == 0);
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use core::cell::*;
-use core::default::Default;
-use std::mem::drop;
-
-#[test]
-fn smoketest_cell() {
- let x = Cell::new(10);
- assert!(x == Cell::new(10));
- assert!(x.get() == 10);
- x.set(20);
- assert!(x == Cell::new(20));
- assert!(x.get() == 20);
-
- let y = Cell::new((30, 40));
- assert!(y == Cell::new((30, 40)));
- assert!(y.get() == (30, 40));
-}
-
-#[test]
-fn cell_has_sensible_show() {
- let x = Cell::new("foo bar");
- assert!(format!("{:?}", x).contains(x.get()));
-
- x.set("baz qux");
- assert!(format!("{:?}", x).contains(x.get()));
-}
-
-#[test]
-fn ref_and_refmut_have_sensible_show() {
- let refcell = RefCell::new("foo");
-
- let refcell_refmut = refcell.borrow_mut();
- assert!(format!("{:?}", refcell_refmut).contains("foo"));
- drop(refcell_refmut);
-
- let refcell_ref = refcell.borrow();
- assert!(format!("{:?}", refcell_ref).contains("foo"));
- drop(refcell_ref);
-}
-
-#[test]
-fn double_imm_borrow() {
- let x = RefCell::new(0);
- let _b1 = x.borrow();
- x.borrow();
-}
-
-#[test]
-fn no_mut_then_imm_borrow() {
- let x = RefCell::new(0);
- let _b1 = x.borrow_mut();
- assert!(x.try_borrow().is_err());
-}
-
-#[test]
-fn no_imm_then_borrow_mut() {
- let x = RefCell::new(0);
- let _b1 = x.borrow();
- assert!(x.try_borrow_mut().is_err());
-}
-
-#[test]
-fn no_double_borrow_mut() {
- let x = RefCell::new(0);
- assert!(x.try_borrow().is_ok());
- let _b1 = x.borrow_mut();
- assert!(x.try_borrow().is_err());
-}
-
-#[test]
-fn imm_release_borrow_mut() {
- let x = RefCell::new(0);
- {
- let _b1 = x.borrow();
- }
- x.borrow_mut();
-}
-
-#[test]
-fn mut_release_borrow_mut() {
- let x = RefCell::new(0);
- {
- let _b1 = x.borrow_mut();
- }
- x.borrow();
-}
-
-#[test]
-fn double_borrow_single_release_no_borrow_mut() {
- let x = RefCell::new(0);
- let _b1 = x.borrow();
- {
- let _b2 = x.borrow();
- }
- assert!(x.try_borrow().is_ok());
- assert!(x.try_borrow_mut().is_err());
-}
-
-#[test]
-#[should_panic]
-fn discard_doesnt_unborrow() {
- let x = RefCell::new(0);
- let _b = x.borrow();
- let _ = _b;
- let _b = x.borrow_mut();
-}
-
-#[test]
-fn ref_clone_updates_flag() {
- let x = RefCell::new(0);
- {
- let b1 = x.borrow();
- assert!(x.try_borrow().is_ok());
- assert!(x.try_borrow_mut().is_err());
- {
- let _b2 = Ref::clone(&b1);
- assert!(x.try_borrow().is_ok());
- assert!(x.try_borrow_mut().is_err());
- }
- assert!(x.try_borrow().is_ok());
- assert!(x.try_borrow_mut().is_err());
- }
- assert!(x.try_borrow().is_ok());
- assert!(x.try_borrow_mut().is_ok());
-}
-
-#[test]
-fn ref_map_does_not_update_flag() {
- let x = RefCell::new(Some(5));
- {
- let b1: Ref<Option<u32>> = x.borrow();
- assert!(x.try_borrow().is_ok());
- assert!(x.try_borrow_mut().is_err());
- {
- let b2: Ref<u32> = Ref::map(b1, |o| o.as_ref().unwrap());
- assert_eq!(*b2, 5);
- assert!(x.try_borrow().is_ok());
- assert!(x.try_borrow_mut().is_err());
- }
- assert!(x.try_borrow().is_ok());
- assert!(x.try_borrow_mut().is_ok());
- }
- assert!(x.try_borrow().is_ok());
- assert!(x.try_borrow_mut().is_ok());
-}
-
-#[test]
-fn ref_map_accessor() {
- struct X(RefCell<(u32, char)>);
- impl X {
- fn accessor(&self) -> Ref<u32> {
- Ref::map(self.0.borrow(), |tuple| &tuple.0)
- }
- }
- let x = X(RefCell::new((7, 'z')));
- let d: Ref<u32> = x.accessor();
- assert_eq!(*d, 7);
-}
-
-#[test]
-fn ref_mut_map_accessor() {
- struct X(RefCell<(u32, char)>);
- impl X {
- fn accessor(&self) -> RefMut<u32> {
- RefMut::map(self.0.borrow_mut(), |tuple| &mut tuple.0)
- }
- }
- let x = X(RefCell::new((7, 'z')));
- {
- let mut d: RefMut<u32> = x.accessor();
- assert_eq!(*d, 7);
- *d += 1;
- }
- assert_eq!(*x.0.borrow(), (8, 'z'));
-}
-
-#[test]
-fn as_ptr() {
- let c1: Cell<usize> = Cell::new(0);
- c1.set(1);
- assert_eq!(1, unsafe { *c1.as_ptr() });
-
- let c2: Cell<usize> = Cell::new(0);
- unsafe { *c2.as_ptr() = 1; }
- assert_eq!(1, c2.get());
-
- let r1: RefCell<usize> = RefCell::new(0);
- *r1.borrow_mut() = 1;
- assert_eq!(1, unsafe { *r1.as_ptr() });
-
- let r2: RefCell<usize> = RefCell::new(0);
- unsafe { *r2.as_ptr() = 1; }
- assert_eq!(1, *r2.borrow());
-}
-
-#[test]
-fn cell_default() {
- let cell: Cell<u32> = Default::default();
- assert_eq!(0, cell.get());
-}
-
-#[test]
-fn cell_set() {
- let cell = Cell::new(10);
- cell.set(20);
- assert_eq!(20, cell.get());
-
- let cell = Cell::new("Hello".to_owned());
- cell.set("World".to_owned());
- assert_eq!("World".to_owned(), cell.into_inner());
-}
-
-#[test]
-fn cell_replace() {
- let cell = Cell::new(10);
- assert_eq!(10, cell.replace(20));
- assert_eq!(20, cell.get());
-
- let cell = Cell::new("Hello".to_owned());
- assert_eq!("Hello".to_owned(), cell.replace("World".to_owned()));
- assert_eq!("World".to_owned(), cell.into_inner());
-}
-
-#[test]
-fn cell_into_inner() {
- let cell = Cell::new(10);
- assert_eq!(10, cell.into_inner());
-
- let cell = Cell::new("Hello world".to_owned());
- assert_eq!("Hello world".to_owned(), cell.into_inner());
-}
-
-#[test]
-fn refcell_default() {
- let cell: RefCell<u64> = Default::default();
- assert_eq!(0, *cell.borrow());
-}
-
-#[test]
-fn unsafe_cell_unsized() {
- let cell: &UnsafeCell<[i32]> = &UnsafeCell::new([1, 2, 3]);
- {
- let val: &mut [i32] = unsafe { &mut *cell.get() };
- val[0] = 4;
- val[2] = 5;
- }
- let comp: &mut [i32] = &mut [4, 2, 5];
- assert_eq!(unsafe { &mut *cell.get() }, comp);
-}
-
-#[test]
-fn refcell_unsized() {
- let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
- {
- let b = &mut *cell.borrow_mut();
- b[0] = 4;
- b[2] = 5;
- }
- let comp: &mut [i32] = &mut [4, 2, 5];
- assert_eq!(&*cell.borrow(), comp);
-}
-
-#[test]
-fn refcell_ref_coercion() {
- let cell: RefCell<[i32; 3]> = RefCell::new([1, 2, 3]);
- {
- let mut cellref: RefMut<[i32; 3]> = cell.borrow_mut();
- cellref[0] = 4;
- let mut coerced: RefMut<[i32]> = cellref;
- coerced[2] = 5;
- }
- {
- let comp: &mut [i32] = &mut [4, 2, 5];
- let cellref: Ref<[i32; 3]> = cell.borrow();
- assert_eq!(&*cellref, comp);
- let coerced: Ref<[i32]> = cellref;
- assert_eq!(&*coerced, comp);
- }
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use std::{char,str};
-use std::convert::TryFrom;
-
-#[test]
-fn test_convert() {
- assert_eq!(u32::from('a'), 0x61);
- assert_eq!(char::from(b'\0'), '\0');
- assert_eq!(char::from(b'a'), 'a');
- assert_eq!(char::from(b'\xFF'), '\u{FF}');
- assert_eq!(char::try_from(0_u32), Ok('\0'));
- assert_eq!(char::try_from(0x61_u32), Ok('a'));
- assert_eq!(char::try_from(0xD7FF_u32), Ok('\u{D7FF}'));
- assert!(char::try_from(0xD800_u32).is_err());
- assert!(char::try_from(0xDFFF_u32).is_err());
- assert_eq!(char::try_from(0xE000_u32), Ok('\u{E000}'));
- assert_eq!(char::try_from(0x10FFFF_u32), Ok('\u{10FFFF}'));
- assert!(char::try_from(0x110000_u32).is_err());
- assert!(char::try_from(0xFFFF_FFFF_u32).is_err());
-}
-
-#[test]
-fn test_is_lowercase() {
- assert!('a'.is_lowercase());
- assert!('ö'.is_lowercase());
- assert!('ß'.is_lowercase());
- assert!(!'Ü'.is_lowercase());
- assert!(!'P'.is_lowercase());
-}
-
-#[test]
-fn test_is_uppercase() {
- assert!(!'h'.is_uppercase());
- assert!(!'ä'.is_uppercase());
- assert!(!'ß'.is_uppercase());
- assert!('Ö'.is_uppercase());
- assert!('T'.is_uppercase());
-}
-
-#[test]
-fn test_is_whitespace() {
- assert!(' '.is_whitespace());
- assert!('\u{2007}'.is_whitespace());
- assert!('\t'.is_whitespace());
- assert!('\n'.is_whitespace());
- assert!(!'a'.is_whitespace());
- assert!(!'_'.is_whitespace());
- assert!(!'\u{0}'.is_whitespace());
-}
-
-#[test]
-fn test_to_digit() {
- assert_eq!('0'.to_digit(10), Some(0));
- assert_eq!('1'.to_digit(2), Some(1));
- assert_eq!('2'.to_digit(3), Some(2));
- assert_eq!('9'.to_digit(10), Some(9));
- assert_eq!('a'.to_digit(16), Some(10));
- assert_eq!('A'.to_digit(16), Some(10));
- assert_eq!('b'.to_digit(16), Some(11));
- assert_eq!('B'.to_digit(16), Some(11));
- assert_eq!('z'.to_digit(36), Some(35));
- assert_eq!('Z'.to_digit(36), Some(35));
- assert_eq!(' '.to_digit(10), None);
- assert_eq!('$'.to_digit(36), None);
-}
-
-#[test]
-fn test_to_lowercase() {
- fn lower(c: char) -> String {
- let iter: String = c.to_lowercase().collect();
- let disp: String = c.to_lowercase().to_string();
- assert_eq!(iter, disp);
- iter
- }
- assert_eq!(lower('A'), "a");
- assert_eq!(lower('Ö'), "ö");
- assert_eq!(lower('ß'), "ß");
- assert_eq!(lower('Ü'), "ü");
- assert_eq!(lower('💩'), "💩");
- assert_eq!(lower('Σ'), "σ");
- assert_eq!(lower('Τ'), "τ");
- assert_eq!(lower('Ι'), "ι");
- assert_eq!(lower('Γ'), "γ");
- assert_eq!(lower('Μ'), "μ");
- assert_eq!(lower('Α'), "α");
- assert_eq!(lower('Σ'), "σ");
- assert_eq!(lower('Dž'), "dž");
- assert_eq!(lower('fi'), "fi");
- assert_eq!(lower('İ'), "i\u{307}");
-}
-
-#[test]
-fn test_to_uppercase() {
- fn upper(c: char) -> String {
- let iter: String = c.to_uppercase().collect();
- let disp: String = c.to_uppercase().to_string();
- assert_eq!(iter, disp);
- iter
- }
- assert_eq!(upper('a'), "A");
- assert_eq!(upper('ö'), "Ö");
- assert_eq!(upper('ß'), "SS"); // not ẞ: Latin capital letter sharp s
- assert_eq!(upper('ü'), "Ü");
- assert_eq!(upper('💩'), "💩");
-
- assert_eq!(upper('σ'), "Σ");
- assert_eq!(upper('τ'), "Τ");
- assert_eq!(upper('ι'), "Ι");
- assert_eq!(upper('γ'), "Γ");
- assert_eq!(upper('μ'), "Μ");
- assert_eq!(upper('α'), "Α");
- assert_eq!(upper('ς'), "Σ");
- assert_eq!(upper('Dž'), "DŽ");
- assert_eq!(upper('fi'), "FI");
- assert_eq!(upper('ᾀ'), "ἈΙ");
-}
-
-#[test]
-fn test_is_control() {
- assert!('\u{0}'.is_control());
- assert!('\u{3}'.is_control());
- assert!('\u{6}'.is_control());
- assert!('\u{9}'.is_control());
- assert!('\u{7f}'.is_control());
- assert!('\u{92}'.is_control());
- assert!(!'\u{20}'.is_control());
- assert!(!'\u{55}'.is_control());
- assert!(!'\u{68}'.is_control());
-}
-
-#[test]
-fn test_is_digit() {
- assert!('2'.is_numeric());
- assert!('7'.is_numeric());
- assert!(!'c'.is_numeric());
- assert!(!'i'.is_numeric());
- assert!(!'z'.is_numeric());
- assert!(!'Q'.is_numeric());
-}
-
-#[test]
-fn test_escape_debug() {
- fn string(c: char) -> String {
- let iter: String = c.escape_debug().collect();
- let disp: String = c.escape_debug().to_string();
- assert_eq!(iter, disp);
- iter
- }
- assert_eq!(string('\n'), "\\n");
- assert_eq!(string('\r'), "\\r");
- assert_eq!(string('\''), "\\'");
- assert_eq!(string('"'), "\\\"");
- assert_eq!(string(' '), " ");
- assert_eq!(string('a'), "a");
- assert_eq!(string('~'), "~");
- assert_eq!(string('é'), "é");
- assert_eq!(string('文'), "文");
- assert_eq!(string('\x00'), "\\u{0}");
- assert_eq!(string('\x1f'), "\\u{1f}");
- assert_eq!(string('\x7f'), "\\u{7f}");
- assert_eq!(string('\u{80}'), "\\u{80}");
- assert_eq!(string('\u{ff}'), "\u{ff}");
- assert_eq!(string('\u{11b}'), "\u{11b}");
- assert_eq!(string('\u{1d4b6}'), "\u{1d4b6}");
- assert_eq!(string('\u{200b}'),"\\u{200b}"); // zero width space
- assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1
- assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2
-}
-
-#[test]
-fn test_escape_default() {
- fn string(c: char) -> String {
- let iter: String = c.escape_default().collect();
- let disp: String = c.escape_default().to_string();
- assert_eq!(iter, disp);
- iter
- }
- assert_eq!(string('\n'), "\\n");
- assert_eq!(string('\r'), "\\r");
- assert_eq!(string('\''), "\\'");
- assert_eq!(string('"'), "\\\"");
- assert_eq!(string(' '), " ");
- assert_eq!(string('a'), "a");
- assert_eq!(string('~'), "~");
- assert_eq!(string('é'), "\\u{e9}");
- assert_eq!(string('\x00'), "\\u{0}");
- assert_eq!(string('\x1f'), "\\u{1f}");
- assert_eq!(string('\x7f'), "\\u{7f}");
- assert_eq!(string('\u{80}'), "\\u{80}");
- assert_eq!(string('\u{ff}'), "\\u{ff}");
- assert_eq!(string('\u{11b}'), "\\u{11b}");
- assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}");
- assert_eq!(string('\u{200b}'), "\\u{200b}"); // zero width space
- assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1
- assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2
-}
-
-#[test]
-fn test_escape_unicode() {
- fn string(c: char) -> String {
- let iter: String = c.escape_unicode().collect();
- let disp: String = c.escape_unicode().to_string();
- assert_eq!(iter, disp);
- iter
- }
-
- assert_eq!(string('\x00'), "\\u{0}");
- assert_eq!(string('\n'), "\\u{a}");
- assert_eq!(string(' '), "\\u{20}");
- assert_eq!(string('a'), "\\u{61}");
- assert_eq!(string('\u{11b}'), "\\u{11b}");
- assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}");
-}
-
-#[test]
-fn test_encode_utf8() {
- fn check(input: char, expect: &[u8]) {
- let mut buf = [0; 4];
- let ptr = buf.as_ptr();
- let s = input.encode_utf8(&mut buf);
- assert_eq!(s.as_ptr() as usize, ptr as usize);
- assert!(str::from_utf8(s.as_bytes()).is_ok());
- assert_eq!(s.as_bytes(), expect);
- }
-
- check('x', &[0x78]);
- check('\u{e9}', &[0xc3, 0xa9]);
- check('\u{a66e}', &[0xea, 0x99, 0xae]);
- check('\u{1f4a9}', &[0xf0, 0x9f, 0x92, 0xa9]);
-}
-
-#[test]
-fn test_encode_utf16() {
- fn check(input: char, expect: &[u16]) {
- let mut buf = [0; 2];
- let ptr = buf.as_mut_ptr();
- let b = input.encode_utf16(&mut buf);
- assert_eq!(b.as_mut_ptr() as usize, ptr as usize);
- assert_eq!(b, expect);
- }
-
- check('x', &[0x0078]);
- check('\u{e9}', &[0x00e9]);
- check('\u{a66e}', &[0xa66e]);
- check('\u{1f4a9}', &[0xd83d, 0xdca9]);
-}
-
-#[test]
-fn test_len_utf16() {
- assert!('x'.len_utf16() == 1);
- assert!('\u{e9}'.len_utf16() == 1);
- assert!('\u{a66e}'.len_utf16() == 1);
- assert!('\u{1f4a9}'.len_utf16() == 2);
-}
-
-#[test]
-fn test_decode_utf16() {
- fn check(s: &[u16], expected: &[Result<char, u16>]) {
- let v = char::decode_utf16(s.iter().cloned())
- .map(|r| r.map_err(|e| e.unpaired_surrogate()))
- .collect::<Vec<_>>();
- assert_eq!(v, expected);
- }
- check(&[0xD800, 0x41, 0x42], &[Err(0xD800), Ok('A'), Ok('B')]);
- check(&[0xD800, 0], &[Err(0xD800), Ok('\0')]);
-}
-
-#[test]
-fn ed_iterator_specializations() {
- // Check counting
- assert_eq!('\n'.escape_default().count(), 2);
- assert_eq!('c'.escape_default().count(), 1);
- assert_eq!(' '.escape_default().count(), 1);
- assert_eq!('\\'.escape_default().count(), 2);
- assert_eq!('\''.escape_default().count(), 2);
-
- // Check nth
-
- // Check that OoB is handled correctly
- assert_eq!('\n'.escape_default().nth(2), None);
- assert_eq!('c'.escape_default().nth(1), None);
- assert_eq!(' '.escape_default().nth(1), None);
- assert_eq!('\\'.escape_default().nth(2), None);
- assert_eq!('\''.escape_default().nth(2), None);
-
- // Check the first char
- assert_eq!('\n'.escape_default().nth(0), Some('\\'));
- assert_eq!('c'.escape_default().nth(0), Some('c'));
- assert_eq!(' '.escape_default().nth(0), Some(' '));
- assert_eq!('\\'.escape_default().nth(0), Some('\\'));
- assert_eq!('\''.escape_default().nth(0), Some('\\'));
-
- // Check the second char
- assert_eq!('\n'.escape_default().nth(1), Some('n'));
- assert_eq!('\\'.escape_default().nth(1), Some('\\'));
- assert_eq!('\''.escape_default().nth(1), Some('\''));
-
- // Check the last char
- assert_eq!('\n'.escape_default().last(), Some('n'));
- assert_eq!('c'.escape_default().last(), Some('c'));
- assert_eq!(' '.escape_default().last(), Some(' '));
- assert_eq!('\\'.escape_default().last(), Some('\\'));
- assert_eq!('\''.escape_default().last(), Some('\''));
-}
-
-#[test]
-fn eu_iterator_specializations() {
- fn check(c: char) {
- let len = c.escape_unicode().count();
-
- // Check OoB
- assert_eq!(c.escape_unicode().nth(len), None);
-
- // For all possible in-bound offsets
- let mut iter = c.escape_unicode();
- for offset in 0..len {
- // Check last
- assert_eq!(iter.clone().last(), Some('}'));
-
- // Check len
- assert_eq!(iter.len(), len - offset);
-
- // Check size_hint (= len in ExactSizeIterator)
- assert_eq!(iter.size_hint(), (iter.len(), Some(iter.len())));
-
- // Check counting
- assert_eq!(iter.clone().count(), len - offset);
-
- // Check nth
- assert_eq!(c.escape_unicode().nth(offset), iter.next());
- }
-
- // Check post-last
- assert_eq!(iter.clone().last(), None);
- assert_eq!(iter.clone().count(), 0);
- }
-
- check('\u{0}');
- check('\u{1}');
- check('\u{12}');
- check('\u{123}');
- check('\u{1234}');
- check('\u{12340}');
- check('\u{10FFFF}');
-}
-
-#[test]
-fn test_decode_utf8() {
- macro_rules! assert_decode_utf8 {
- ($input_bytes: expr, $expected_str: expr) => {
- let input_bytes: &[u8] = &$input_bytes;
- let s = char::decode_utf8(input_bytes.iter().cloned())
- .map(|r_b| r_b.unwrap_or('\u{FFFD}'))
- .collect::<String>();
- assert_eq!(s, $expected_str,
- "input bytes: {:?}, expected str: {:?}, result: {:?}",
- input_bytes, $expected_str, s);
- assert_eq!(String::from_utf8_lossy(&$input_bytes), $expected_str);
- }
- }
-
- assert_decode_utf8!([], "");
- assert_decode_utf8!([0x41], "A");
- assert_decode_utf8!([0xC1, 0x81], "��");
- assert_decode_utf8!([0xE2, 0x99, 0xA5], "♥");
- assert_decode_utf8!([0xE2, 0x99, 0xA5, 0x41], "♥A");
- assert_decode_utf8!([0xE2, 0x99], "�");
- assert_decode_utf8!([0xE2, 0x99, 0x41], "�A");
- assert_decode_utf8!([0xC0], "�");
- assert_decode_utf8!([0xC0, 0x41], "�A");
- assert_decode_utf8!([0x80], "�");
- assert_decode_utf8!([0x80, 0x41], "�A");
- assert_decode_utf8!([0xFE], "�");
- assert_decode_utf8!([0xFE, 0x41], "�A");
- assert_decode_utf8!([0xFF], "�");
- assert_decode_utf8!([0xFF, 0x41], "�A");
- assert_decode_utf8!([0xC0, 0x80], "��");
-
- // Surrogates
- assert_decode_utf8!([0xED, 0x9F, 0xBF], "\u{D7FF}");
- assert_decode_utf8!([0xED, 0xA0, 0x80], "���");
- assert_decode_utf8!([0xED, 0xBF, 0x80], "���");
- assert_decode_utf8!([0xEE, 0x80, 0x80], "\u{E000}");
-
- // char::MAX
- assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0xBF], "\u{10FFFF}");
- assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0x41], "�A");
- assert_decode_utf8!([0xF4, 0x90, 0x80, 0x80], "����");
-
- // 5 and 6 bytes sequence
- // Part of the original design of UTF-8,
- // but invalid now that UTF-8 is artificially restricted to match the range of UTF-16.
- assert_decode_utf8!([0xF8, 0x80, 0x80, 0x80, 0x80], "�����");
- assert_decode_utf8!([0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], "������");
-}
+++ /dev/null
-// Copyright 2014-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.
-
-#[test]
-fn test_borrowed_clone() {
- let x = 5;
- let y: &i32 = &x;
- let z: &i32 = (&y).clone();
- assert_eq!(*z, 5);
-}
-
-#[test]
-fn test_clone_from() {
- let a = box 5;
- let mut b = box 10;
- b.clone_from(&a);
- assert_eq!(*b, 5);
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use core::cmp::Ordering::{Less, Greater, Equal};
-
-#[test]
-fn test_int_totalord() {
- assert_eq!(5.cmp(&10), Less);
- assert_eq!(10.cmp(&5), Greater);
- assert_eq!(5.cmp(&5), Equal);
- assert_eq!((-5).cmp(&12), Less);
- assert_eq!(12.cmp(&-5), Greater);
-}
-
-#[test]
-fn test_mut_int_totalord() {
- assert_eq!((&mut 5).cmp(&&mut 10), Less);
- assert_eq!((&mut 10).cmp(&&mut 5), Greater);
- assert_eq!((&mut 5).cmp(&&mut 5), Equal);
- assert_eq!((&mut -5).cmp(&&mut 12), Less);
- assert_eq!((&mut 12).cmp(&&mut -5), Greater);
-}
-
-#[test]
-fn test_ordering_reverse() {
- assert_eq!(Less.reverse(), Greater);
- assert_eq!(Equal.reverse(), Equal);
- assert_eq!(Greater.reverse(), Less);
-}
-
-#[test]
-fn test_ordering_order() {
- assert!(Less < Equal);
- assert_eq!(Greater.cmp(&Less), Greater);
-}
-
-#[test]
-fn test_ordering_then() {
- assert_eq!(Equal.then(Less), Less);
- assert_eq!(Equal.then(Equal), Equal);
- assert_eq!(Equal.then(Greater), Greater);
- assert_eq!(Less.then(Less), Less);
- assert_eq!(Less.then(Equal), Less);
- assert_eq!(Less.then(Greater), Less);
- assert_eq!(Greater.then(Less), Greater);
- assert_eq!(Greater.then(Equal), Greater);
- assert_eq!(Greater.then(Greater), Greater);
-}
-
-#[test]
-fn test_ordering_then_with() {
- assert_eq!(Equal.then_with(|| Less), Less);
- assert_eq!(Equal.then_with(|| Equal), Equal);
- assert_eq!(Equal.then_with(|| Greater), Greater);
- assert_eq!(Less.then_with(|| Less), Less);
- assert_eq!(Less.then_with(|| Equal), Less);
- assert_eq!(Less.then_with(|| Greater), Less);
- assert_eq!(Greater.then_with(|| Less), Greater);
- assert_eq!(Greater.then_with(|| Equal), Greater);
- assert_eq!(Greater.then_with(|| Greater), Greater);
-}
-
-#[test]
-fn test_user_defined_eq() {
- // Our type.
- struct SketchyNum {
- num : isize
- }
-
- // Our implementation of `PartialEq` to support `==` and `!=`.
- impl PartialEq for SketchyNum {
- // Our custom eq allows numbers which are near each other to be equal! :D
- fn eq(&self, other: &SketchyNum) -> bool {
- (self.num - other.num).abs() < 5
- }
- }
-
- // Now these binary operators will work when applied!
- assert!(SketchyNum {num: 37} == SketchyNum {num: 34});
- assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
-}
+++ /dev/null
-// Copyright 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.
-
-mod debug_struct {
- use std::fmt;
-
- #[test]
- fn test_empty() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_struct("Foo").finish()
- }
- }
-
- assert_eq!("Foo", format!("{:?}", Foo));
- assert_eq!("Foo", format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_single() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_struct("Foo")
- .field("bar", &true)
- .finish()
- }
- }
-
- assert_eq!("Foo { bar: true }", format!("{:?}", Foo));
- assert_eq!(
-"Foo {
- bar: true
-}",
- format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_multiple() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_struct("Foo")
- .field("bar", &true)
- .field("baz", &format_args!("{}/{}", 10, 20))
- .finish()
- }
- }
-
- assert_eq!("Foo { bar: true, baz: 10/20 }", format!("{:?}", Foo));
- assert_eq!(
-"Foo {
- bar: true,
- baz: 10/20
-}",
- format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_nested() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_struct("Foo")
- .field("bar", &true)
- .field("baz", &format_args!("{}/{}", 10, 20))
- .finish()
- }
- }
-
- struct Bar;
-
- impl fmt::Debug for Bar {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_struct("Bar")
- .field("foo", &Foo)
- .field("hello", &"world")
- .finish()
- }
- }
-
- assert_eq!("Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }",
- format!("{:?}", Bar));
- assert_eq!(
-"Bar {
- foo: Foo {
- bar: true,
- baz: 10/20
- },
- hello: \"world\"
-}",
- format!("{:#?}", Bar));
- }
-}
-
-mod debug_tuple {
- use std::fmt;
-
- #[test]
- fn test_empty() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_tuple("Foo").finish()
- }
- }
-
- assert_eq!("Foo", format!("{:?}", Foo));
- assert_eq!("Foo", format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_single() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_tuple("Foo")
- .field(&true)
- .finish()
- }
- }
-
- assert_eq!("Foo(true)", format!("{:?}", Foo));
- assert_eq!(
-"Foo(
- true
-)",
- format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_multiple() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_tuple("Foo")
- .field(&true)
- .field(&format_args!("{}/{}", 10, 20))
- .finish()
- }
- }
-
- assert_eq!("Foo(true, 10/20)", format!("{:?}", Foo));
- assert_eq!(
-"Foo(
- true,
- 10/20
-)",
- format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_nested() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_tuple("Foo")
- .field(&true)
- .field(&format_args!("{}/{}", 10, 20))
- .finish()
- }
- }
-
- struct Bar;
-
- impl fmt::Debug for Bar {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_tuple("Bar")
- .field(&Foo)
- .field(&"world")
- .finish()
- }
- }
-
- assert_eq!("Bar(Foo(true, 10/20), \"world\")",
- format!("{:?}", Bar));
- assert_eq!(
-"Bar(
- Foo(
- true,
- 10/20
- ),
- \"world\"
-)",
- format!("{:#?}", Bar));
- }
-}
-
-mod debug_map {
- use std::fmt;
-
- #[test]
- fn test_empty() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_map().finish()
- }
- }
-
- assert_eq!("{}", format!("{:?}", Foo));
- assert_eq!("{}", format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_single() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_map()
- .entry(&"bar", &true)
- .finish()
- }
- }
-
- assert_eq!("{\"bar\": true}", format!("{:?}", Foo));
- assert_eq!(
-"{
- \"bar\": true
-}",
- format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_multiple() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_map()
- .entry(&"bar", &true)
- .entry(&10, &format_args!("{}/{}", 10, 20))
- .finish()
- }
- }
-
- assert_eq!("{\"bar\": true, 10: 10/20}", format!("{:?}", Foo));
- assert_eq!(
-"{
- \"bar\": true,
- 10: 10/20
-}",
- format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_nested() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_map()
- .entry(&"bar", &true)
- .entry(&10, &format_args!("{}/{}", 10, 20))
- .finish()
- }
- }
-
- struct Bar;
-
- impl fmt::Debug for Bar {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_map()
- .entry(&"foo", &Foo)
- .entry(&Foo, &"world")
- .finish()
- }
- }
-
- assert_eq!("{\"foo\": {\"bar\": true, 10: 10/20}, \
- {\"bar\": true, 10: 10/20}: \"world\"}",
- format!("{:?}", Bar));
- assert_eq!(
-"{
- \"foo\": {
- \"bar\": true,
- 10: 10/20
- },
- {
- \"bar\": true,
- 10: 10/20
- }: \"world\"
-}",
- format!("{:#?}", Bar));
- }
-}
-
-mod debug_set {
- use std::fmt;
-
- #[test]
- fn test_empty() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_set().finish()
- }
- }
-
- assert_eq!("{}", format!("{:?}", Foo));
- assert_eq!("{}", format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_single() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_set()
- .entry(&true)
- .finish()
- }
- }
-
- assert_eq!("{true}", format!("{:?}", Foo));
- assert_eq!(
-"{
- true
-}",
- format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_multiple() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_set()
- .entry(&true)
- .entry(&format_args!("{}/{}", 10, 20))
- .finish()
- }
- }
-
- assert_eq!("{true, 10/20}", format!("{:?}", Foo));
- assert_eq!(
-"{
- true,
- 10/20
-}",
- format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_nested() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_set()
- .entry(&true)
- .entry(&format_args!("{}/{}", 10, 20))
- .finish()
- }
- }
-
- struct Bar;
-
- impl fmt::Debug for Bar {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_set()
- .entry(&Foo)
- .entry(&"world")
- .finish()
- }
- }
-
- assert_eq!("{{true, 10/20}, \"world\"}",
- format!("{:?}", Bar));
- assert_eq!(
-"{
- {
- true,
- 10/20
- },
- \"world\"
-}",
- format!("{:#?}", Bar));
- }
-}
-
-mod debug_list {
- use std::fmt;
-
- #[test]
- fn test_empty() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_list().finish()
- }
- }
-
- assert_eq!("[]", format!("{:?}", Foo));
- assert_eq!("[]", format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_single() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_list()
- .entry(&true)
- .finish()
- }
- }
-
- assert_eq!("[true]", format!("{:?}", Foo));
- assert_eq!(
-"[
- true
-]",
- format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_multiple() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_list()
- .entry(&true)
- .entry(&format_args!("{}/{}", 10, 20))
- .finish()
- }
- }
-
- assert_eq!("[true, 10/20]", format!("{:?}", Foo));
- assert_eq!(
-"[
- true,
- 10/20
-]",
- format!("{:#?}", Foo));
- }
-
- #[test]
- fn test_nested() {
- struct Foo;
-
- impl fmt::Debug for Foo {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_list()
- .entry(&true)
- .entry(&format_args!("{}/{}", 10, 20))
- .finish()
- }
- }
-
- struct Bar;
-
- impl fmt::Debug for Bar {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_list()
- .entry(&Foo)
- .entry(&"world")
- .finish()
- }
- }
-
- assert_eq!("[[true, 10/20], \"world\"]",
- format!("{:?}", Bar));
- assert_eq!(
-"[
- [
- true,
- 10/20
- ],
- \"world\"
-]",
- format!("{:#?}", Bar));
- }
-}
+++ /dev/null
-// Copyright 2014 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.
-
-#[test]
-fn test_format_f64() {
- assert_eq!("1", format!("{:.0}", 1.0f64));
- assert_eq!("9", format!("{:.0}", 9.4f64));
- assert_eq!("10", format!("{:.0}", 9.9f64));
- assert_eq!("9.8", format!("{:.1}", 9.849f64));
- assert_eq!("9.9", format!("{:.1}", 9.851f64));
- assert_eq!("1", format!("{:.0}", 0.5f64));
- assert_eq!("1.23456789e6", format!("{:e}", 1234567.89f64));
- assert_eq!("1.23456789e3", format!("{:e}", 1234.56789f64));
- assert_eq!("1.23456789E6", format!("{:E}", 1234567.89f64));
- assert_eq!("1.23456789E3", format!("{:E}", 1234.56789f64));
-}
-
-#[test]
-fn test_format_f32() {
- assert_eq!("1", format!("{:.0}", 1.0f32));
- assert_eq!("9", format!("{:.0}", 9.4f32));
- assert_eq!("10", format!("{:.0}", 9.9f32));
- assert_eq!("9.8", format!("{:.1}", 9.849f32));
- assert_eq!("9.9", format!("{:.1}", 9.851f32));
- assert_eq!("1", format!("{:.0}", 0.5f32));
- assert_eq!("1.2345679e6", format!("{:e}", 1234567.89f32));
- assert_eq!("1.2345679e3", format!("{:e}", 1234.56789f32));
- assert_eq!("1.2345679E6", format!("{:E}", 1234567.89f32));
- assert_eq!("1.2345679E3", format!("{:E}", 1234.56789f32));
-}
+++ /dev/null
-// Copyright 2014 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.
-
-mod builders;
-mod float;
-mod num;
-
-#[test]
-fn test_format_flags() {
- // No residual flags left by pointer formatting
- let p = "".as_ptr();
- assert_eq!(format!("{:p} {:x}", p, 16), format!("{:p} 10", p));
-
- assert_eq!(format!("{: >3}", 'a'), " a");
-}
-
-#[test]
-fn test_pointer_formats_data_pointer() {
- let b: &[u8] = b"";
- let s: &str = "";
- assert_eq!(format!("{:p}", s), format!("{:p}", s.as_ptr()));
- assert_eq!(format!("{:p}", b), format!("{:p}", b.as_ptr()));
-}
-
-#[test]
-fn test_estimated_capacity() {
- assert_eq!(format_args!("").estimated_capacity(), 0);
- assert_eq!(format_args!("{}", "").estimated_capacity(), 0);
- assert_eq!(format_args!("Hello").estimated_capacity(), 5);
- assert_eq!(format_args!("Hello, {}!", "").estimated_capacity(), 16);
- assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0);
- assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32);
-}
+++ /dev/null
-// Copyright 2014 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.
-
-#[test]
-fn test_format_int() {
- // Formatting integers should select the right implementation based off
- // the type of the argument. Also, hex/octal/binary should be defined
- // for integers, but they shouldn't emit the negative sign.
- assert!(format!("{}", 1isize) == "1");
- assert!(format!("{}", 1i8) == "1");
- assert!(format!("{}", 1i16) == "1");
- assert!(format!("{}", 1i32) == "1");
- assert!(format!("{}", 1i64) == "1");
- assert!(format!("{}", -1isize) == "-1");
- assert!(format!("{}", -1i8) == "-1");
- assert!(format!("{}", -1i16) == "-1");
- assert!(format!("{}", -1i32) == "-1");
- assert!(format!("{}", -1i64) == "-1");
- assert!(format!("{:?}", 1isize) == "1");
- assert!(format!("{:?}", 1i8) == "1");
- assert!(format!("{:?}", 1i16) == "1");
- assert!(format!("{:?}", 1i32) == "1");
- assert!(format!("{:?}", 1i64) == "1");
- assert!(format!("{:b}", 1isize) == "1");
- assert!(format!("{:b}", 1i8) == "1");
- assert!(format!("{:b}", 1i16) == "1");
- assert!(format!("{:b}", 1i32) == "1");
- assert!(format!("{:b}", 1i64) == "1");
- assert!(format!("{:x}", 1isize) == "1");
- assert!(format!("{:x}", 1i8) == "1");
- assert!(format!("{:x}", 1i16) == "1");
- assert!(format!("{:x}", 1i32) == "1");
- assert!(format!("{:x}", 1i64) == "1");
- assert!(format!("{:X}", 1isize) == "1");
- assert!(format!("{:X}", 1i8) == "1");
- assert!(format!("{:X}", 1i16) == "1");
- assert!(format!("{:X}", 1i32) == "1");
- assert!(format!("{:X}", 1i64) == "1");
- assert!(format!("{:o}", 1isize) == "1");
- assert!(format!("{:o}", 1i8) == "1");
- assert!(format!("{:o}", 1i16) == "1");
- assert!(format!("{:o}", 1i32) == "1");
- assert!(format!("{:o}", 1i64) == "1");
-
- assert!(format!("{}", 1usize) == "1");
- assert!(format!("{}", 1u8) == "1");
- assert!(format!("{}", 1u16) == "1");
- assert!(format!("{}", 1u32) == "1");
- assert!(format!("{}", 1u64) == "1");
- assert!(format!("{:?}", 1usize) == "1");
- assert!(format!("{:?}", 1u8) == "1");
- assert!(format!("{:?}", 1u16) == "1");
- assert!(format!("{:?}", 1u32) == "1");
- assert!(format!("{:?}", 1u64) == "1");
- assert!(format!("{:b}", 1usize) == "1");
- assert!(format!("{:b}", 1u8) == "1");
- assert!(format!("{:b}", 1u16) == "1");
- assert!(format!("{:b}", 1u32) == "1");
- assert!(format!("{:b}", 1u64) == "1");
- assert!(format!("{:x}", 1usize) == "1");
- assert!(format!("{:x}", 1u8) == "1");
- assert!(format!("{:x}", 1u16) == "1");
- assert!(format!("{:x}", 1u32) == "1");
- assert!(format!("{:x}", 1u64) == "1");
- assert!(format!("{:X}", 1usize) == "1");
- assert!(format!("{:X}", 1u8) == "1");
- assert!(format!("{:X}", 1u16) == "1");
- assert!(format!("{:X}", 1u32) == "1");
- assert!(format!("{:X}", 1u64) == "1");
- assert!(format!("{:o}", 1usize) == "1");
- assert!(format!("{:o}", 1u8) == "1");
- assert!(format!("{:o}", 1u16) == "1");
- assert!(format!("{:o}", 1u32) == "1");
- assert!(format!("{:o}", 1u64) == "1");
-
- // Test a larger number
- assert!(format!("{:b}", 55) == "110111");
- assert!(format!("{:o}", 55) == "67");
- assert!(format!("{}", 55) == "55");
- assert!(format!("{:x}", 55) == "37");
- assert!(format!("{:X}", 55) == "37");
-}
-
-#[test]
-fn test_format_int_zero() {
- assert!(format!("{}", 0) == "0");
- assert!(format!("{:?}", 0) == "0");
- assert!(format!("{:b}", 0) == "0");
- assert!(format!("{:o}", 0) == "0");
- assert!(format!("{:x}", 0) == "0");
- assert!(format!("{:X}", 0) == "0");
-
- assert!(format!("{}", 0u32) == "0");
- assert!(format!("{:?}", 0u32) == "0");
- assert!(format!("{:b}", 0u32) == "0");
- assert!(format!("{:o}", 0u32) == "0");
- assert!(format!("{:x}", 0u32) == "0");
- assert!(format!("{:X}", 0u32) == "0");
-}
-
-#[test]
-fn test_format_int_flags() {
- assert!(format!("{:3}", 1) == " 1");
- assert!(format!("{:>3}", 1) == " 1");
- assert!(format!("{:>+3}", 1) == " +1");
- assert!(format!("{:<3}", 1) == "1 ");
- assert!(format!("{:#}", 1) == "1");
- assert!(format!("{:#x}", 10) == "0xa");
- assert!(format!("{:#X}", 10) == "0xA");
- assert!(format!("{:#5x}", 10) == " 0xa");
- assert!(format!("{:#o}", 10) == "0o12");
- assert!(format!("{:08x}", 10) == "0000000a");
- assert!(format!("{:8x}", 10) == " a");
- assert!(format!("{:<8x}", 10) == "a ");
- assert!(format!("{:>8x}", 10) == " a");
- assert!(format!("{:#08x}", 10) == "0x00000a");
- assert!(format!("{:08}", -10) == "-0000010");
- assert!(format!("{:x}", !0u8) == "ff");
- assert!(format!("{:X}", !0u8) == "FF");
- assert!(format!("{:b}", !0u8) == "11111111");
- assert!(format!("{:o}", !0u8) == "377");
- assert!(format!("{:#x}", !0u8) == "0xff");
- assert!(format!("{:#X}", !0u8) == "0xFF");
- assert!(format!("{:#b}", !0u8) == "0b11111111");
- assert!(format!("{:#o}", !0u8) == "0o377");
-}
-
-#[test]
-fn test_format_int_sign_padding() {
- assert!(format!("{:+5}", 1) == " +1");
- assert!(format!("{:+5}", -1) == " -1");
- assert!(format!("{:05}", 1) == "00001");
- assert!(format!("{:05}", -1) == "-0001");
- assert!(format!("{:+05}", 1) == "+0001");
- assert!(format!("{:+05}", -1) == "-0001");
-}
-
-#[test]
-fn test_format_int_twos_complement() {
- use core::{i8, i16, i32, i64};
- assert!(format!("{}", i8::MIN) == "-128");
- assert!(format!("{}", i16::MIN) == "-32768");
- assert!(format!("{}", i32::MIN) == "-2147483648");
- assert!(format!("{}", i64::MIN) == "-9223372036854775808");
-}
+++ /dev/null
-// Copyright 2014 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.
-
-mod sip;
-
-use std::hash::{Hash, Hasher};
-use std::default::Default;
-
-struct MyHasher {
- hash: u64,
-}
-
-impl Default for MyHasher {
- fn default() -> MyHasher {
- MyHasher { hash: 0 }
- }
-}
-
-impl Hasher for MyHasher {
- fn write(&mut self, buf: &[u8]) {
- for byte in buf {
- self.hash += *byte as u64;
- }
- }
- fn finish(&self) -> u64 { self.hash }
-}
-
-
-#[test]
-fn test_writer_hasher() {
- fn hash<T: Hash>(t: &T) -> u64 {
- let mut s = MyHasher { hash: 0 };
- t.hash(&mut s);
- s.finish()
- }
-
- assert_eq!(hash(&()), 0);
-
- assert_eq!(hash(&5_u8), 5);
- assert_eq!(hash(&5_u16), 5);
- assert_eq!(hash(&5_u32), 5);
- assert_eq!(hash(&5_u64), 5);
- assert_eq!(hash(&5_usize), 5);
-
- assert_eq!(hash(&5_i8), 5);
- assert_eq!(hash(&5_i16), 5);
- assert_eq!(hash(&5_i32), 5);
- assert_eq!(hash(&5_i64), 5);
- assert_eq!(hash(&5_isize), 5);
-
- assert_eq!(hash(&false), 0);
- assert_eq!(hash(&true), 1);
-
- assert_eq!(hash(&'a'), 97);
-
- let s: &str = "a";
- assert_eq!(hash(& s), 97 + 0xFF);
- let s: Box<str> = String::from("a").into_boxed_str();
- assert_eq!(hash(& s), 97 + 0xFF);
- let cs: &[u8] = &[1, 2, 3];
- assert_eq!(hash(& cs), 9);
- let cs: Box<[u8]> = Box::new([1, 2, 3]);
- assert_eq!(hash(& cs), 9);
-
- // FIXME (#18248) Add tests for hashing Rc<str> and Rc<[T]>
-
- let ptr = 5_usize as *const i32;
- assert_eq!(hash(&ptr), 5);
-
- let ptr = 5_usize as *mut i32;
- assert_eq!(hash(&ptr), 5);
-}
-
-struct Custom { hash: u64 }
-struct CustomHasher { output: u64 }
-
-impl Hasher for CustomHasher {
- fn finish(&self) -> u64 { self.output }
- fn write(&mut self, _: &[u8]) { panic!() }
- fn write_u64(&mut self, data: u64) { self.output = data; }
-}
-
-impl Default for CustomHasher {
- fn default() -> CustomHasher {
- CustomHasher { output: 0 }
- }
-}
-
-impl Hash for Custom {
- fn hash<H: Hasher>(&self, state: &mut H) {
- state.write_u64(self.hash);
- }
-}
-
-#[test]
-fn test_custom_state() {
- fn hash<T: Hash>(t: &T) -> u64 {
- let mut c = CustomHasher { output: 0 };
- t.hash(&mut c);
- c.finish()
- }
-
- assert_eq!(hash(&Custom { hash: 5 }), 5);
-}
+++ /dev/null
-// Copyright 2014 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.
-
-#![allow(deprecated)]
-
-use core::hash::{Hash, Hasher};
-use core::hash::{SipHasher, SipHasher13, SipHasher24};
-use core::{slice, mem};
-
-// Hash just the bytes of the slice, without length prefix
-struct Bytes<'a>(&'a [u8]);
-
-impl<'a> Hash for Bytes<'a> {
- #[allow(unused_must_use)]
- fn hash<H: Hasher>(&self, state: &mut H) {
- let Bytes(v) = *self;
- state.write(v);
- }
-}
-
-macro_rules! u8to64_le {
- ($buf:expr, $i:expr) =>
- ($buf[0+$i] as u64 |
- ($buf[1+$i] as u64) << 8 |
- ($buf[2+$i] as u64) << 16 |
- ($buf[3+$i] as u64) << 24 |
- ($buf[4+$i] as u64) << 32 |
- ($buf[5+$i] as u64) << 40 |
- ($buf[6+$i] as u64) << 48 |
- ($buf[7+$i] as u64) << 56);
- ($buf:expr, $i:expr, $len:expr) =>
- ({
- let mut t = 0;
- let mut out = 0;
- while t < $len {
- out |= ($buf[t+$i] as u64) << t*8;
- t += 1;
- }
- out
- });
-}
-
-fn hash_with<H: Hasher, T: Hash>(mut st: H, x: &T) -> u64 {
- x.hash(&mut st);
- st.finish()
-}
-
-fn hash<T: Hash>(x: &T) -> u64 {
- hash_with(SipHasher::new(), x)
-}
-
-#[test]
-#[allow(unused_must_use)]
-fn test_siphash_1_3() {
- let vecs : [[u8; 8]; 64] = [
- [ 0xdc, 0xc4, 0x0f, 0x05, 0x58, 0x01, 0xac, 0xab ],
- [ 0x93, 0xca, 0x57, 0x7d, 0xf3, 0x9b, 0xf4, 0xc9 ],
- [ 0x4d, 0xd4, 0xc7, 0x4d, 0x02, 0x9b, 0xcb, 0x82 ],
- [ 0xfb, 0xf7, 0xdd, 0xe7, 0xb8, 0x0a, 0xf8, 0x8b ],
- [ 0x28, 0x83, 0xd3, 0x88, 0x60, 0x57, 0x75, 0xcf ],
- [ 0x67, 0x3b, 0x53, 0x49, 0x2f, 0xd5, 0xf9, 0xde ],
- [ 0xa7, 0x22, 0x9f, 0xc5, 0x50, 0x2b, 0x0d, 0xc5 ],
- [ 0x40, 0x11, 0xb1, 0x9b, 0x98, 0x7d, 0x92, 0xd3 ],
- [ 0x8e, 0x9a, 0x29, 0x8d, 0x11, 0x95, 0x90, 0x36 ],
- [ 0xe4, 0x3d, 0x06, 0x6c, 0xb3, 0x8e, 0xa4, 0x25 ],
- [ 0x7f, 0x09, 0xff, 0x92, 0xee, 0x85, 0xde, 0x79 ],
- [ 0x52, 0xc3, 0x4d, 0xf9, 0xc1, 0x18, 0xc1, 0x70 ],
- [ 0xa2, 0xd9, 0xb4, 0x57, 0xb1, 0x84, 0xa3, 0x78 ],
- [ 0xa7, 0xff, 0x29, 0x12, 0x0c, 0x76, 0x6f, 0x30 ],
- [ 0x34, 0x5d, 0xf9, 0xc0, 0x11, 0xa1, 0x5a, 0x60 ],
- [ 0x56, 0x99, 0x51, 0x2a, 0x6d, 0xd8, 0x20, 0xd3 ],
- [ 0x66, 0x8b, 0x90, 0x7d, 0x1a, 0xdd, 0x4f, 0xcc ],
- [ 0x0c, 0xd8, 0xdb, 0x63, 0x90, 0x68, 0xf2, 0x9c ],
- [ 0x3e, 0xe6, 0x73, 0xb4, 0x9c, 0x38, 0xfc, 0x8f ],
- [ 0x1c, 0x7d, 0x29, 0x8d, 0xe5, 0x9d, 0x1f, 0xf2 ],
- [ 0x40, 0xe0, 0xcc, 0xa6, 0x46, 0x2f, 0xdc, 0xc0 ],
- [ 0x44, 0xf8, 0x45, 0x2b, 0xfe, 0xab, 0x92, 0xb9 ],
- [ 0x2e, 0x87, 0x20, 0xa3, 0x9b, 0x7b, 0xfe, 0x7f ],
- [ 0x23, 0xc1, 0xe6, 0xda, 0x7f, 0x0e, 0x5a, 0x52 ],
- [ 0x8c, 0x9c, 0x34, 0x67, 0xb2, 0xae, 0x64, 0xf4 ],
- [ 0x79, 0x09, 0x5b, 0x70, 0x28, 0x59, 0xcd, 0x45 ],
- [ 0xa5, 0x13, 0x99, 0xca, 0xe3, 0x35, 0x3e, 0x3a ],
- [ 0x35, 0x3b, 0xde, 0x4a, 0x4e, 0xc7, 0x1d, 0xa9 ],
- [ 0x0d, 0xd0, 0x6c, 0xef, 0x02, 0xed, 0x0b, 0xfb ],
- [ 0xf4, 0xe1, 0xb1, 0x4a, 0xb4, 0x3c, 0xd9, 0x88 ],
- [ 0x63, 0xe6, 0xc5, 0x43, 0xd6, 0x11, 0x0f, 0x54 ],
- [ 0xbc, 0xd1, 0x21, 0x8c, 0x1f, 0xdd, 0x70, 0x23 ],
- [ 0x0d, 0xb6, 0xa7, 0x16, 0x6c, 0x7b, 0x15, 0x81 ],
- [ 0xbf, 0xf9, 0x8f, 0x7a, 0xe5, 0xb9, 0x54, 0x4d ],
- [ 0x3e, 0x75, 0x2a, 0x1f, 0x78, 0x12, 0x9f, 0x75 ],
- [ 0x91, 0x6b, 0x18, 0xbf, 0xbe, 0xa3, 0xa1, 0xce ],
- [ 0x06, 0x62, 0xa2, 0xad, 0xd3, 0x08, 0xf5, 0x2c ],
- [ 0x57, 0x30, 0xc3, 0xa3, 0x2d, 0x1c, 0x10, 0xb6 ],
- [ 0xa1, 0x36, 0x3a, 0xae, 0x96, 0x74, 0xf4, 0xb3 ],
- [ 0x92, 0x83, 0x10, 0x7b, 0x54, 0x57, 0x6b, 0x62 ],
- [ 0x31, 0x15, 0xe4, 0x99, 0x32, 0x36, 0xd2, 0xc1 ],
- [ 0x44, 0xd9, 0x1a, 0x3f, 0x92, 0xc1, 0x7c, 0x66 ],
- [ 0x25, 0x88, 0x13, 0xc8, 0xfe, 0x4f, 0x70, 0x65 ],
- [ 0xa6, 0x49, 0x89, 0xc2, 0xd1, 0x80, 0xf2, 0x24 ],
- [ 0x6b, 0x87, 0xf8, 0xfa, 0xed, 0x1c, 0xca, 0xc2 ],
- [ 0x96, 0x21, 0x04, 0x9f, 0xfc, 0x4b, 0x16, 0xc2 ],
- [ 0x23, 0xd6, 0xb1, 0x68, 0x93, 0x9c, 0x6e, 0xa1 ],
- [ 0xfd, 0x14, 0x51, 0x8b, 0x9c, 0x16, 0xfb, 0x49 ],
- [ 0x46, 0x4c, 0x07, 0xdf, 0xf8, 0x43, 0x31, 0x9f ],
- [ 0xb3, 0x86, 0xcc, 0x12, 0x24, 0xaf, 0xfd, 0xc6 ],
- [ 0x8f, 0x09, 0x52, 0x0a, 0xd1, 0x49, 0xaf, 0x7e ],
- [ 0x9a, 0x2f, 0x29, 0x9d, 0x55, 0x13, 0xf3, 0x1c ],
- [ 0x12, 0x1f, 0xf4, 0xa2, 0xdd, 0x30, 0x4a, 0xc4 ],
- [ 0xd0, 0x1e, 0xa7, 0x43, 0x89, 0xe9, 0xfa, 0x36 ],
- [ 0xe6, 0xbc, 0xf0, 0x73, 0x4c, 0xb3, 0x8f, 0x31 ],
- [ 0x80, 0xe9, 0xa7, 0x70, 0x36, 0xbf, 0x7a, 0xa2 ],
- [ 0x75, 0x6d, 0x3c, 0x24, 0xdb, 0xc0, 0xbc, 0xb4 ],
- [ 0x13, 0x15, 0xb7, 0xfd, 0x52, 0xd8, 0xf8, 0x23 ],
- [ 0x08, 0x8a, 0x7d, 0xa6, 0x4d, 0x5f, 0x03, 0x8f ],
- [ 0x48, 0xf1, 0xe8, 0xb7, 0xe5, 0xd0, 0x9c, 0xd8 ],
- [ 0xee, 0x44, 0xa6, 0xf7, 0xbc, 0xe6, 0xf4, 0xf6 ],
- [ 0xf2, 0x37, 0x18, 0x0f, 0xd8, 0x9a, 0xc5, 0xae ],
- [ 0xe0, 0x94, 0x66, 0x4b, 0x15, 0xf6, 0xb2, 0xc3 ],
- [ 0xa8, 0xb3, 0xbb, 0xb7, 0x62, 0x90, 0x19, 0x9d ]
- ];
-
- let k0 = 0x_07_06_05_04_03_02_01_00;
- let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08;
- let mut buf = Vec::new();
- let mut t = 0;
- let mut state_inc = SipHasher13::new_with_keys(k0, k1);
-
- while t < 64 {
- let vec = u8to64_le!(vecs[t], 0);
- let out = hash_with(SipHasher13::new_with_keys(k0, k1), &Bytes(&buf));
- assert_eq!(vec, out);
-
- let full = hash_with(SipHasher13::new_with_keys(k0, k1), &Bytes(&buf));
- let i = state_inc.finish();
-
- assert_eq!(full, i);
- assert_eq!(full, vec);
-
- buf.push(t as u8);
- Hasher::write(&mut state_inc, &[t as u8]);
-
- t += 1;
- }
-}
-
-#[test]
-#[allow(unused_must_use)]
-fn test_siphash_2_4() {
- let vecs : [[u8; 8]; 64] = [
- [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
- [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
- [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
- [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ],
- [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ],
- [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ],
- [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ],
- [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ],
- [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ],
- [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ],
- [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ],
- [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ],
- [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ],
- [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ],
- [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ],
- [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ],
- [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ],
- [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ],
- [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ],
- [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ],
- [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ],
- [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ],
- [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ],
- [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ],
- [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ],
- [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ],
- [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ],
- [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ],
- [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ],
- [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ],
- [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ],
- [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ],
- [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ],
- [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ],
- [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ],
- [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ],
- [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ],
- [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ],
- [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ],
- [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ],
- [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ],
- [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ],
- [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ],
- [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ],
- [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ],
- [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ],
- [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ],
- [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ],
- [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ],
- [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ],
- [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ],
- [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ],
- [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ],
- [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ],
- [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ],
- [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ],
- [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ],
- [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ],
- [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ],
- [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ],
- [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ],
- [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ],
- [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ],
- [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]
- ];
-
- let k0 = 0x_07_06_05_04_03_02_01_00;
- let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08;
- let mut buf = Vec::new();
- let mut t = 0;
- let mut state_inc = SipHasher24::new_with_keys(k0, k1);
-
- while t < 64 {
- let vec = u8to64_le!(vecs[t], 0);
- let out = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
- assert_eq!(vec, out);
-
- let full = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
- let i = state_inc.finish();
-
- assert_eq!(full, i);
- assert_eq!(full, vec);
-
- buf.push(t as u8);
- Hasher::write(&mut state_inc, &[t as u8]);
-
- t += 1;
- }
-}
-#[test] #[cfg(target_arch = "arm")]
-fn test_hash_usize() {
- let val = 0xdeadbeef_deadbeef_u64;
- assert!(hash(&(val as u64)) != hash(&(val as usize)));
- assert_eq!(hash(&(val as u32)), hash(&(val as usize)));
-}
-#[test] #[cfg(target_arch = "x86_64")]
-fn test_hash_usize() {
- let val = 0xdeadbeef_deadbeef_u64;
- assert_eq!(hash(&(val as u64)), hash(&(val as usize)));
- assert!(hash(&(val as u32)) != hash(&(val as usize)));
-}
-#[test] #[cfg(target_arch = "x86")]
-fn test_hash_usize() {
- let val = 0xdeadbeef_deadbeef_u64;
- assert!(hash(&(val as u64)) != hash(&(val as usize)));
- assert_eq!(hash(&(val as u32)), hash(&(val as usize)));
-}
-
-#[test]
-fn test_hash_idempotent() {
- let val64 = 0xdeadbeef_deadbeef_u64;
- assert_eq!(hash(&val64), hash(&val64));
- let val32 = 0xdeadbeef_u32;
- assert_eq!(hash(&val32), hash(&val32));
-}
-
-#[test]
-fn test_hash_no_bytes_dropped_64() {
- let val = 0xdeadbeef_deadbeef_u64;
-
- assert!(hash(&val) != hash(&zero_byte(val, 0)));
- assert!(hash(&val) != hash(&zero_byte(val, 1)));
- assert!(hash(&val) != hash(&zero_byte(val, 2)));
- assert!(hash(&val) != hash(&zero_byte(val, 3)));
- assert!(hash(&val) != hash(&zero_byte(val, 4)));
- assert!(hash(&val) != hash(&zero_byte(val, 5)));
- assert!(hash(&val) != hash(&zero_byte(val, 6)));
- assert!(hash(&val) != hash(&zero_byte(val, 7)));
-
- fn zero_byte(val: u64, byte: usize) -> u64 {
- assert!(byte < 8);
- val & !(0xff << (byte * 8))
- }
-}
-
-#[test]
-fn test_hash_no_bytes_dropped_32() {
- let val = 0xdeadbeef_u32;
-
- assert!(hash(&val) != hash(&zero_byte(val, 0)));
- assert!(hash(&val) != hash(&zero_byte(val, 1)));
- assert!(hash(&val) != hash(&zero_byte(val, 2)));
- assert!(hash(&val) != hash(&zero_byte(val, 3)));
-
- fn zero_byte(val: u32, byte: usize) -> u32 {
- assert!(byte < 4);
- val & !(0xff << (byte * 8))
- }
-}
-
-#[test]
-fn test_hash_no_concat_alias() {
- let s = ("aa", "bb");
- let t = ("aabb", "");
- let u = ("a", "abb");
-
- assert!(s != t && t != u);
- assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u));
-
- let u = [1, 0, 0, 0];
- let v = (&u[..1], &u[1..3], &u[3..]);
- let w = (&u[..], &u[4..4], &u[4..4]);
-
- assert!(v != w);
- assert!(hash(&v) != hash(&w));
-}
-
-#[test]
-fn test_write_short_works() {
- let test_usize = 0xd0c0b0a0usize;
- let mut h1 = SipHasher24::new();
- h1.write_usize(test_usize);
- h1.write(b"bytes");
- h1.write(b"string");
- h1.write_u8(0xFFu8);
- h1.write_u8(0x01u8);
- let mut h2 = SipHasher24::new();
- h2.write(unsafe {
- slice::from_raw_parts(&test_usize as *const _ as *const u8,
- mem::size_of::<usize>())
- });
- h2.write(b"bytes");
- h2.write(b"string");
- h2.write(&[0xFFu8, 0x01u8]);
- assert_eq!(h1.finish(), h2.finish());
-}
+++ /dev/null
-// Copyright 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.
-
-use core::any::TypeId;
-
-#[test]
-fn test_typeid_sized_types() {
- struct X; struct Y(u32);
-
- assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
- assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
- assert!(TypeId::of::<X>() != TypeId::of::<Y>());
-}
-
-#[test]
-fn test_typeid_unsized_types() {
- trait Z {}
- struct X(str); struct Y(Z + 'static);
-
- assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
- assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
- assert!(TypeId::of::<X>() != TypeId::of::<Y>());
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use core::iter::*;
-use core::{i8, i16, isize};
-use core::usize;
-
-#[test]
-fn test_lt() {
- let empty: [isize; 0] = [];
- let xs = [1,2,3];
- let ys = [1,2,0];
-
- assert!(!xs.iter().lt(ys.iter()));
- assert!(!xs.iter().le(ys.iter()));
- assert!( xs.iter().gt(ys.iter()));
- assert!( xs.iter().ge(ys.iter()));
-
- assert!( ys.iter().lt(xs.iter()));
- assert!( ys.iter().le(xs.iter()));
- assert!(!ys.iter().gt(xs.iter()));
- assert!(!ys.iter().ge(xs.iter()));
-
- assert!( empty.iter().lt(xs.iter()));
- assert!( empty.iter().le(xs.iter()));
- assert!(!empty.iter().gt(xs.iter()));
- assert!(!empty.iter().ge(xs.iter()));
-
- // Sequence with NaN
- let u = [1.0f64, 2.0];
- let v = [0.0f64/0.0, 3.0];
-
- assert!(!u.iter().lt(v.iter()));
- assert!(!u.iter().le(v.iter()));
- assert!(!u.iter().gt(v.iter()));
- assert!(!u.iter().ge(v.iter()));
-
- let a = [0.0f64/0.0];
- let b = [1.0f64];
- let c = [2.0f64];
-
- assert!(a.iter().lt(b.iter()) == (a[0] < b[0]));
- assert!(a.iter().le(b.iter()) == (a[0] <= b[0]));
- assert!(a.iter().gt(b.iter()) == (a[0] > b[0]));
- assert!(a.iter().ge(b.iter()) == (a[0] >= b[0]));
-
- assert!(c.iter().lt(b.iter()) == (c[0] < b[0]));
- assert!(c.iter().le(b.iter()) == (c[0] <= b[0]));
- assert!(c.iter().gt(b.iter()) == (c[0] > b[0]));
- assert!(c.iter().ge(b.iter()) == (c[0] >= b[0]));
-}
-
-#[test]
-fn test_multi_iter() {
- let xs = [1,2,3,4];
- let ys = [4,3,2,1];
- assert!(xs.iter().eq(ys.iter().rev()));
- assert!(xs.iter().lt(xs.iter().skip(2)));
-}
-
-#[test]
-fn test_counter_from_iter() {
- let it = (0..).step_by(5).take(10);
- let xs: Vec<isize> = FromIterator::from_iter(it);
- assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
-}
-
-#[test]
-fn test_iterator_chain() {
- let xs = [0, 1, 2, 3, 4, 5];
- let ys = [30, 40, 50, 60];
- let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
- let it = xs.iter().chain(&ys);
- let mut i = 0;
- for &x in it {
- assert_eq!(x, expected[i]);
- i += 1;
- }
- assert_eq!(i, expected.len());
-
- let ys = (30..).step_by(10).take(4);
- let it = xs.iter().cloned().chain(ys);
- let mut i = 0;
- for x in it {
- assert_eq!(x, expected[i]);
- i += 1;
- }
- assert_eq!(i, expected.len());
-}
-
-#[test]
-fn test_iterator_chain_nth() {
- let xs = [0, 1, 2, 3, 4, 5];
- let ys = [30, 40, 50, 60];
- let zs = [];
- let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
- for (i, x) in expected.iter().enumerate() {
- assert_eq!(Some(x), xs.iter().chain(&ys).nth(i));
- }
- assert_eq!(zs.iter().chain(&xs).nth(0), Some(&0));
-
- let mut it = xs.iter().chain(&zs);
- assert_eq!(it.nth(5), Some(&5));
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_iterator_chain_last() {
- let xs = [0, 1, 2, 3, 4, 5];
- let ys = [30, 40, 50, 60];
- let zs = [];
- assert_eq!(xs.iter().chain(&ys).last(), Some(&60));
- assert_eq!(zs.iter().chain(&ys).last(), Some(&60));
- assert_eq!(ys.iter().chain(&zs).last(), Some(&60));
- assert_eq!(zs.iter().chain(&zs).last(), None);
-}
-
-#[test]
-fn test_iterator_chain_count() {
- let xs = [0, 1, 2, 3, 4, 5];
- let ys = [30, 40, 50, 60];
- let zs = [];
- assert_eq!(xs.iter().chain(&ys).count(), 10);
- assert_eq!(zs.iter().chain(&ys).count(), 4);
-}
-
-#[test]
-fn test_iterator_chain_find() {
- let xs = [0, 1, 2, 3, 4, 5];
- let ys = [30, 40, 50, 60];
- let mut iter = xs.iter().chain(&ys);
- assert_eq!(iter.find(|&&i| i == 4), Some(&4));
- assert_eq!(iter.next(), Some(&5));
- assert_eq!(iter.find(|&&i| i == 40), Some(&40));
- assert_eq!(iter.next(), Some(&50));
- assert_eq!(iter.find(|&&i| i == 100), None);
- assert_eq!(iter.next(), None);
-}
-
-#[test]
-fn test_filter_map() {
- let it = (0..).step_by(1).take(10)
- .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
- assert_eq!(it.collect::<Vec<usize>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
-}
-
-#[test]
-fn test_iterator_enumerate() {
- let xs = [0, 1, 2, 3, 4, 5];
- let it = xs.iter().enumerate();
- for (i, &x) in it {
- assert_eq!(i, x);
- }
-}
-
-#[test]
-fn test_iterator_enumerate_nth() {
- let xs = [0, 1, 2, 3, 4, 5];
- for (i, &x) in xs.iter().enumerate() {
- assert_eq!(i, x);
- }
-
- let mut it = xs.iter().enumerate();
- while let Some((i, &x)) = it.nth(0) {
- assert_eq!(i, x);
- }
-
- let mut it = xs.iter().enumerate();
- while let Some((i, &x)) = it.nth(1) {
- assert_eq!(i, x);
- }
-
- let (i, &x) = xs.iter().enumerate().nth(3).unwrap();
- assert_eq!(i, x);
- assert_eq!(i, 3);
-}
-
-#[test]
-fn test_iterator_enumerate_count() {
- let xs = [0, 1, 2, 3, 4, 5];
- assert_eq!(xs.iter().count(), 6);
-}
-
-#[test]
-fn test_iterator_filter_count() {
- let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
- assert_eq!(xs.iter().filter(|&&x| x % 2 == 0).count(), 5);
-}
-
-#[test]
-fn test_iterator_peekable() {
- let xs = vec![0, 1, 2, 3, 4, 5];
- let mut it = xs.iter().cloned().peekable();
-
- assert_eq!(it.len(), 6);
- assert_eq!(it.peek().unwrap(), &0);
- assert_eq!(it.len(), 6);
- assert_eq!(it.next().unwrap(), 0);
- assert_eq!(it.len(), 5);
- assert_eq!(it.next().unwrap(), 1);
- assert_eq!(it.len(), 4);
- assert_eq!(it.next().unwrap(), 2);
- assert_eq!(it.len(), 3);
- assert_eq!(it.peek().unwrap(), &3);
- assert_eq!(it.len(), 3);
- assert_eq!(it.peek().unwrap(), &3);
- assert_eq!(it.len(), 3);
- assert_eq!(it.next().unwrap(), 3);
- assert_eq!(it.len(), 2);
- assert_eq!(it.next().unwrap(), 4);
- assert_eq!(it.len(), 1);
- assert_eq!(it.peek().unwrap(), &5);
- assert_eq!(it.len(), 1);
- assert_eq!(it.next().unwrap(), 5);
- assert_eq!(it.len(), 0);
- assert!(it.peek().is_none());
- assert_eq!(it.len(), 0);
- assert!(it.next().is_none());
- assert_eq!(it.len(), 0);
-}
-
-#[test]
-fn test_iterator_peekable_count() {
- let xs = [0, 1, 2, 3, 4, 5];
- let ys = [10];
- let zs: [i32; 0] = [];
-
- assert_eq!(xs.iter().peekable().count(), 6);
-
- let mut it = xs.iter().peekable();
- assert_eq!(it.peek(), Some(&&0));
- assert_eq!(it.count(), 6);
-
- assert_eq!(ys.iter().peekable().count(), 1);
-
- let mut it = ys.iter().peekable();
- assert_eq!(it.peek(), Some(&&10));
- assert_eq!(it.count(), 1);
-
- assert_eq!(zs.iter().peekable().count(), 0);
-
- let mut it = zs.iter().peekable();
- assert_eq!(it.peek(), None);
-
-}
-
-#[test]
-fn test_iterator_peekable_nth() {
- let xs = [0, 1, 2, 3, 4, 5];
- let mut it = xs.iter().peekable();
-
- assert_eq!(it.peek(), Some(&&0));
- assert_eq!(it.nth(0), Some(&0));
- assert_eq!(it.peek(), Some(&&1));
- assert_eq!(it.nth(1), Some(&2));
- assert_eq!(it.peek(), Some(&&3));
- assert_eq!(it.nth(2), Some(&5));
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_iterator_peekable_last() {
- let xs = [0, 1, 2, 3, 4, 5];
- let ys = [0];
-
- let mut it = xs.iter().peekable();
- assert_eq!(it.peek(), Some(&&0));
- assert_eq!(it.last(), Some(&5));
-
- let mut it = ys.iter().peekable();
- assert_eq!(it.peek(), Some(&&0));
- assert_eq!(it.last(), Some(&0));
-
- let mut it = ys.iter().peekable();
- assert_eq!(it.next(), Some(&0));
- assert_eq!(it.peek(), None);
- assert_eq!(it.last(), None);
-}
-
-/// This is an iterator that follows the Iterator contract,
-/// but it is not fused. After having returned None once, it will start
-/// producing elements if .next() is called again.
-pub struct CycleIter<'a, T: 'a> {
- index: usize,
- data: &'a [T],
-}
-
-pub fn cycle<T>(data: &[T]) -> CycleIter<T> {
- CycleIter {
- index: 0,
- data: data,
- }
-}
-
-impl<'a, T> Iterator for CycleIter<'a, T> {
- type Item = &'a T;
- fn next(&mut self) -> Option<Self::Item> {
- let elt = self.data.get(self.index);
- self.index += 1;
- self.index %= 1 + self.data.len();
- elt
- }
-}
-
-#[test]
-fn test_iterator_peekable_remember_peek_none_1() {
- // Check that the loop using .peek() terminates
- let data = [1, 2, 3];
- let mut iter = cycle(&data).peekable();
-
- let mut n = 0;
- while let Some(_) = iter.next() {
- let is_the_last = iter.peek().is_none();
- assert_eq!(is_the_last, n == data.len() - 1);
- n += 1;
- if n > data.len() { break; }
- }
- assert_eq!(n, data.len());
-}
-
-#[test]
-fn test_iterator_peekable_remember_peek_none_2() {
- let data = [0];
- let mut iter = cycle(&data).peekable();
- iter.next();
- assert_eq!(iter.peek(), None);
- assert_eq!(iter.last(), None);
-}
-
-#[test]
-fn test_iterator_peekable_remember_peek_none_3() {
- let data = [0];
- let mut iter = cycle(&data).peekable();
- iter.peek();
- assert_eq!(iter.nth(0), Some(&0));
-
- let mut iter = cycle(&data).peekable();
- iter.next();
- assert_eq!(iter.peek(), None);
- assert_eq!(iter.nth(0), None);
-}
-
-#[test]
-fn test_iterator_take_while() {
- let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
- let ys = [0, 1, 2, 3, 5, 13];
- let it = xs.iter().take_while(|&x| *x < 15);
- let mut i = 0;
- for x in it {
- assert_eq!(*x, ys[i]);
- i += 1;
- }
- assert_eq!(i, ys.len());
-}
-
-#[test]
-fn test_iterator_skip_while() {
- let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
- let ys = [15, 16, 17, 19];
- let it = xs.iter().skip_while(|&x| *x < 15);
- let mut i = 0;
- for x in it {
- assert_eq!(*x, ys[i]);
- i += 1;
- }
- assert_eq!(i, ys.len());
-}
-
-#[test]
-fn test_iterator_skip() {
- let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
- let ys = [13, 15, 16, 17, 19, 20, 30];
- let mut it = xs.iter().skip(5);
- let mut i = 0;
- while let Some(&x) = it.next() {
- assert_eq!(x, ys[i]);
- i += 1;
- assert_eq!(it.len(), xs.len()-5-i);
- }
- assert_eq!(i, ys.len());
- assert_eq!(it.len(), 0);
-}
-
-#[test]
-fn test_iterator_skip_doubleended() {
- let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
- let mut it = xs.iter().rev().skip(5);
- assert_eq!(it.next(), Some(&15));
- assert_eq!(it.by_ref().rev().next(), Some(&0));
- assert_eq!(it.next(), Some(&13));
- assert_eq!(it.by_ref().rev().next(), Some(&1));
- assert_eq!(it.next(), Some(&5));
- assert_eq!(it.by_ref().rev().next(), Some(&2));
- assert_eq!(it.next(), Some(&3));
- assert_eq!(it.next(), None);
- let mut it = xs.iter().rev().skip(5).rev();
- assert_eq!(it.next(), Some(&0));
- assert_eq!(it.rev().next(), Some(&15));
- let mut it_base = xs.iter();
- {
- let mut it = it_base.by_ref().skip(5).rev();
- assert_eq!(it.next(), Some(&30));
- assert_eq!(it.next(), Some(&20));
- assert_eq!(it.next(), Some(&19));
- assert_eq!(it.next(), Some(&17));
- assert_eq!(it.next(), Some(&16));
- assert_eq!(it.next(), Some(&15));
- assert_eq!(it.next(), Some(&13));
- assert_eq!(it.next(), None);
- }
- // make sure the skipped parts have not been consumed
- assert_eq!(it_base.next(), Some(&0));
- assert_eq!(it_base.next(), Some(&1));
- assert_eq!(it_base.next(), Some(&2));
- assert_eq!(it_base.next(), Some(&3));
- assert_eq!(it_base.next(), Some(&5));
- assert_eq!(it_base.next(), None);
- let it = xs.iter().skip(5).rev();
- assert_eq!(it.last(), Some(&13));
-}
-
-#[test]
-fn test_iterator_skip_nth() {
- let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
-
- let mut it = xs.iter().skip(0);
- assert_eq!(it.nth(0), Some(&0));
- assert_eq!(it.nth(1), Some(&2));
-
- let mut it = xs.iter().skip(5);
- assert_eq!(it.nth(0), Some(&13));
- assert_eq!(it.nth(1), Some(&16));
-
- let mut it = xs.iter().skip(12);
- assert_eq!(it.nth(0), None);
-
-}
-
-#[test]
-fn test_iterator_skip_count() {
- let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
-
- assert_eq!(xs.iter().skip(0).count(), 12);
- assert_eq!(xs.iter().skip(1).count(), 11);
- assert_eq!(xs.iter().skip(11).count(), 1);
- assert_eq!(xs.iter().skip(12).count(), 0);
- assert_eq!(xs.iter().skip(13).count(), 0);
-}
-
-#[test]
-fn test_iterator_skip_last() {
- let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
-
- assert_eq!(xs.iter().skip(0).last(), Some(&30));
- assert_eq!(xs.iter().skip(1).last(), Some(&30));
- assert_eq!(xs.iter().skip(11).last(), Some(&30));
- assert_eq!(xs.iter().skip(12).last(), None);
- assert_eq!(xs.iter().skip(13).last(), None);
-
- let mut it = xs.iter().skip(5);
- assert_eq!(it.next(), Some(&13));
- assert_eq!(it.last(), Some(&30));
-}
-
-#[test]
-fn test_iterator_take() {
- let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
- let ys = [0, 1, 2, 3, 5];
- let mut it = xs.iter().take(5);
- let mut i = 0;
- assert_eq!(it.len(), 5);
- while let Some(&x) = it.next() {
- assert_eq!(x, ys[i]);
- i += 1;
- assert_eq!(it.len(), 5-i);
- }
- assert_eq!(i, ys.len());
- assert_eq!(it.len(), 0);
-}
-
-#[test]
-fn test_iterator_take_nth() {
- let xs = [0, 1, 2, 4, 5];
- let mut it = xs.iter();
- {
- let mut take = it.by_ref().take(3);
- let mut i = 0;
- while let Some(&x) = take.nth(0) {
- assert_eq!(x, i);
- i += 1;
- }
- }
- assert_eq!(it.nth(1), Some(&5));
- assert_eq!(it.nth(0), None);
-
- let xs = [0, 1, 2, 3, 4];
- let mut it = xs.iter().take(7);
- let mut i = 1;
- while let Some(&x) = it.nth(1) {
- assert_eq!(x, i);
- i += 2;
- }
-}
-
-#[test]
-fn test_iterator_take_short() {
- let xs = [0, 1, 2, 3];
- let ys = [0, 1, 2, 3];
- let mut it = xs.iter().take(5);
- let mut i = 0;
- assert_eq!(it.len(), 4);
- while let Some(&x) = it.next() {
- assert_eq!(x, ys[i]);
- i += 1;
- assert_eq!(it.len(), 4-i);
- }
- assert_eq!(i, ys.len());
- assert_eq!(it.len(), 0);
-}
-
-#[test]
-fn test_iterator_scan() {
- // test the type inference
- fn add(old: &mut isize, new: &usize) -> Option<f64> {
- *old += *new as isize;
- Some(*old as f64)
- }
- let xs = [0, 1, 2, 3, 4];
- let ys = [0f64, 1.0, 3.0, 6.0, 10.0];
-
- let it = xs.iter().scan(0, add);
- let mut i = 0;
- for x in it {
- assert_eq!(x, ys[i]);
- i += 1;
- }
- assert_eq!(i, ys.len());
-}
-
-#[test]
-fn test_iterator_flat_map() {
- let xs = [0, 3, 6];
- let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8];
- let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3));
- let mut i = 0;
- for x in it {
- assert_eq!(x, ys[i]);
- i += 1;
- }
- assert_eq!(i, ys.len());
-}
-
-#[test]
-fn test_inspect() {
- let xs = [1, 2, 3, 4];
- let mut n = 0;
-
- let ys = xs.iter()
- .cloned()
- .inspect(|_| n += 1)
- .collect::<Vec<usize>>();
-
- assert_eq!(n, xs.len());
- assert_eq!(&xs[..], &ys[..]);
-}
-
-#[test]
-fn test_cycle() {
- let cycle_len = 3;
- let it = (0..).step_by(1).take(cycle_len).cycle();
- assert_eq!(it.size_hint(), (usize::MAX, None));
- for (i, x) in it.take(100).enumerate() {
- assert_eq!(i % cycle_len, x);
- }
-
- let mut it = (0..).step_by(1).take(0).cycle();
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_iterator_nth() {
- let v: &[_] = &[0, 1, 2, 3, 4];
- for i in 0..v.len() {
- assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
- }
- assert_eq!(v.iter().nth(v.len()), None);
-}
-
-#[test]
-fn test_iterator_last() {
- let v: &[_] = &[0, 1, 2, 3, 4];
- assert_eq!(v.iter().last().unwrap(), &4);
- assert_eq!(v[..1].iter().last().unwrap(), &0);
-}
-
-#[test]
-fn test_iterator_len() {
- let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().count(), 4);
- assert_eq!(v[..10].iter().count(), 10);
- assert_eq!(v[..0].iter().count(), 0);
-}
-
-#[test]
-fn test_iterator_sum() {
- let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().cloned().sum::<i32>(), 6);
- assert_eq!(v.iter().cloned().sum::<i32>(), 55);
- assert_eq!(v[..0].iter().cloned().sum::<i32>(), 0);
-}
-
-#[test]
-fn test_iterator_sum_result() {
- let v: &[Result<i32, ()>] = &[Ok(1), Ok(2), Ok(3), Ok(4)];
- assert_eq!(v.iter().cloned().sum::<Result<i32, _>>(), Ok(10));
- let v: &[Result<i32, ()>] = &[Ok(1), Err(()), Ok(3), Ok(4)];
- assert_eq!(v.iter().cloned().sum::<Result<i32, _>>(), Err(()));
-}
-
-#[test]
-fn test_iterator_product() {
- let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().cloned().product::<i32>(), 0);
- assert_eq!(v[1..5].iter().cloned().product::<i32>(), 24);
- assert_eq!(v[..0].iter().cloned().product::<i32>(), 1);
-}
-
-#[test]
-fn test_iterator_product_result() {
- let v: &[Result<i32, ()>] = &[Ok(1), Ok(2), Ok(3), Ok(4)];
- assert_eq!(v.iter().cloned().product::<Result<i32, _>>(), Ok(24));
- let v: &[Result<i32, ()>] = &[Ok(1), Err(()), Ok(3), Ok(4)];
- assert_eq!(v.iter().cloned().product::<Result<i32, _>>(), Err(()));
-}
-
-#[test]
-fn test_iterator_max() {
- let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().cloned().max(), Some(3));
- assert_eq!(v.iter().cloned().max(), Some(10));
- assert_eq!(v[..0].iter().cloned().max(), None);
-}
-
-#[test]
-fn test_iterator_min() {
- let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().cloned().min(), Some(0));
- assert_eq!(v.iter().cloned().min(), Some(0));
- assert_eq!(v[..0].iter().cloned().min(), None);
-}
-
-#[test]
-fn test_iterator_size_hint() {
- let c = (0..).step_by(1);
- let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
- let v2 = &[10, 11, 12];
- let vi = v.iter();
-
- assert_eq!(c.size_hint(), (usize::MAX, None));
- assert_eq!(vi.clone().size_hint(), (10, Some(10)));
-
- assert_eq!(c.clone().take(5).size_hint(), (5, Some(5)));
- assert_eq!(c.clone().skip(5).size_hint().1, None);
- assert_eq!(c.clone().take_while(|_| false).size_hint(), (0, None));
- assert_eq!(c.clone().skip_while(|_| false).size_hint(), (0, None));
- assert_eq!(c.clone().enumerate().size_hint(), (usize::MAX, None));
- assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (usize::MAX, None));
- assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10)));
- assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None));
- assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None));
- assert_eq!(c.clone().map(|_| 0).size_hint(), (usize::MAX, None));
- assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None));
-
- assert_eq!(vi.clone().take(5).size_hint(), (5, Some(5)));
- assert_eq!(vi.clone().take(12).size_hint(), (10, Some(10)));
- assert_eq!(vi.clone().skip(3).size_hint(), (7, Some(7)));
- assert_eq!(vi.clone().skip(12).size_hint(), (0, Some(0)));
- assert_eq!(vi.clone().take_while(|_| false).size_hint(), (0, Some(10)));
- assert_eq!(vi.clone().skip_while(|_| false).size_hint(), (0, Some(10)));
- assert_eq!(vi.clone().enumerate().size_hint(), (10, Some(10)));
- assert_eq!(vi.clone().chain(v2).size_hint(), (13, Some(13)));
- assert_eq!(vi.clone().zip(v2).size_hint(), (3, Some(3)));
- assert_eq!(vi.clone().scan(0, |_,_| Some(0)).size_hint(), (0, Some(10)));
- assert_eq!(vi.clone().filter(|_| false).size_hint(), (0, Some(10)));
- assert_eq!(vi.clone().map(|&i| i+1).size_hint(), (10, Some(10)));
- assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10)));
-}
-
-#[test]
-fn test_collect() {
- let a = vec![1, 2, 3, 4, 5];
- let b: Vec<isize> = a.iter().cloned().collect();
- assert!(a == b);
-}
-
-#[test]
-fn test_all() {
- let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
- assert!(v.iter().all(|&x| x < 10));
- assert!(!v.iter().all(|&x| x % 2 == 0));
- assert!(!v.iter().all(|&x| x > 100));
- assert!(v[..0].iter().all(|_| panic!()));
-}
-
-#[test]
-fn test_any() {
- let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
- assert!(v.iter().any(|&x| x < 10));
- assert!(v.iter().any(|&x| x % 2 == 0));
- assert!(!v.iter().any(|&x| x > 100));
- assert!(!v[..0].iter().any(|_| panic!()));
-}
-
-#[test]
-fn test_find() {
- let v: &[isize] = &[1, 3, 9, 27, 103, 14, 11];
- assert_eq!(*v.iter().find(|&&x| x & 1 == 0).unwrap(), 14);
- assert_eq!(*v.iter().find(|&&x| x % 3 == 0).unwrap(), 3);
- assert!(v.iter().find(|&&x| x % 12 == 0).is_none());
-}
-
-#[test]
-fn test_position() {
- let v = &[1, 3, 9, 27, 103, 14, 11];
- assert_eq!(v.iter().position(|x| *x & 1 == 0).unwrap(), 5);
- assert_eq!(v.iter().position(|x| *x % 3 == 0).unwrap(), 1);
- assert!(v.iter().position(|x| *x % 12 == 0).is_none());
-}
-
-#[test]
-fn test_count() {
- let xs = &[1, 2, 2, 1, 5, 9, 0, 2];
- assert_eq!(xs.iter().filter(|x| **x == 2).count(), 3);
- assert_eq!(xs.iter().filter(|x| **x == 5).count(), 1);
- assert_eq!(xs.iter().filter(|x| **x == 95).count(), 0);
-}
-
-#[test]
-fn test_max_by_key() {
- let xs: &[isize] = &[-3, 0, 1, 5, -10];
- assert_eq!(*xs.iter().max_by_key(|x| x.abs()).unwrap(), -10);
-}
-
-#[test]
-fn test_max_by() {
- let xs: &[isize] = &[-3, 0, 1, 5, -10];
- assert_eq!(*xs.iter().max_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), -10);
-}
-
-#[test]
-fn test_min_by_key() {
- let xs: &[isize] = &[-3, 0, 1, 5, -10];
- assert_eq!(*xs.iter().min_by_key(|x| x.abs()).unwrap(), 0);
-}
-
-#[test]
-fn test_min_by() {
- let xs: &[isize] = &[-3, 0, 1, 5, -10];
- assert_eq!(*xs.iter().min_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), 0);
-}
-
-#[test]
-fn test_by_ref() {
- let mut xs = 0..10;
- // sum the first five values
- let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b);
- assert_eq!(partial_sum, 10);
- assert_eq!(xs.next(), Some(5));
-}
-
-#[test]
-fn test_rev() {
- let xs = [2, 4, 6, 8, 10, 12, 14, 16];
- let mut it = xs.iter();
- it.next();
- it.next();
- assert!(it.rev().cloned().collect::<Vec<isize>>() ==
- vec![16, 14, 12, 10, 8, 6]);
-}
-
-#[test]
-fn test_cloned() {
- let xs = [2, 4, 6, 8];
-
- let mut it = xs.iter().cloned();
- assert_eq!(it.len(), 4);
- assert_eq!(it.next(), Some(2));
- assert_eq!(it.len(), 3);
- assert_eq!(it.next(), Some(4));
- assert_eq!(it.len(), 2);
- assert_eq!(it.next_back(), Some(8));
- assert_eq!(it.len(), 1);
- assert_eq!(it.next_back(), Some(6));
- assert_eq!(it.len(), 0);
- assert_eq!(it.next_back(), None);
-}
-
-#[test]
-fn test_double_ended_map() {
- let xs = [1, 2, 3, 4, 5, 6];
- let mut it = xs.iter().map(|&x| x * -1);
- assert_eq!(it.next(), Some(-1));
- assert_eq!(it.next(), Some(-2));
- assert_eq!(it.next_back(), Some(-6));
- assert_eq!(it.next_back(), Some(-5));
- assert_eq!(it.next(), Some(-3));
- assert_eq!(it.next_back(), Some(-4));
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_double_ended_enumerate() {
- let xs = [1, 2, 3, 4, 5, 6];
- let mut it = xs.iter().cloned().enumerate();
- assert_eq!(it.next(), Some((0, 1)));
- assert_eq!(it.next(), Some((1, 2)));
- assert_eq!(it.next_back(), Some((5, 6)));
- assert_eq!(it.next_back(), Some((4, 5)));
- assert_eq!(it.next_back(), Some((3, 4)));
- assert_eq!(it.next_back(), Some((2, 3)));
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_double_ended_zip() {
- let xs = [1, 2, 3, 4, 5, 6];
- let ys = [1, 2, 3, 7];
- let a = xs.iter().cloned();
- let b = ys.iter().cloned();
- let mut it = a.zip(b);
- assert_eq!(it.next(), Some((1, 1)));
- assert_eq!(it.next(), Some((2, 2)));
- assert_eq!(it.next_back(), Some((4, 7)));
- assert_eq!(it.next_back(), Some((3, 3)));
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_double_ended_filter() {
- let xs = [1, 2, 3, 4, 5, 6];
- let mut it = xs.iter().filter(|&x| *x & 1 == 0);
- assert_eq!(it.next_back().unwrap(), &6);
- assert_eq!(it.next_back().unwrap(), &4);
- assert_eq!(it.next().unwrap(), &2);
- assert_eq!(it.next_back(), None);
-}
-
-#[test]
-fn test_double_ended_filter_map() {
- let xs = [1, 2, 3, 4, 5, 6];
- let mut it = xs.iter().filter_map(|&x| if x & 1 == 0 { Some(x * 2) } else { None });
- assert_eq!(it.next_back().unwrap(), 12);
- assert_eq!(it.next_back().unwrap(), 8);
- assert_eq!(it.next().unwrap(), 4);
- assert_eq!(it.next_back(), None);
-}
-
-#[test]
-fn test_double_ended_chain() {
- let xs = [1, 2, 3, 4, 5];
- let ys = [7, 9, 11];
- let mut it = xs.iter().chain(&ys).rev();
- assert_eq!(it.next().unwrap(), &11);
- assert_eq!(it.next().unwrap(), &9);
- assert_eq!(it.next_back().unwrap(), &1);
- assert_eq!(it.next_back().unwrap(), &2);
- assert_eq!(it.next_back().unwrap(), &3);
- assert_eq!(it.next_back().unwrap(), &4);
- assert_eq!(it.next_back().unwrap(), &5);
- assert_eq!(it.next_back().unwrap(), &7);
- assert_eq!(it.next_back(), None);
-
-
- // test that .chain() is well behaved with an unfused iterator
- struct CrazyIterator(bool);
- impl CrazyIterator { fn new() -> CrazyIterator { CrazyIterator(false) } }
- impl Iterator for CrazyIterator {
- type Item = i32;
- fn next(&mut self) -> Option<i32> {
- if self.0 { Some(99) } else { self.0 = true; None }
- }
- }
-
- impl DoubleEndedIterator for CrazyIterator {
- fn next_back(&mut self) -> Option<i32> {
- self.next()
- }
- }
-
- assert_eq!(CrazyIterator::new().chain(0..10).rev().last(), Some(0));
- assert!((0..10).chain(CrazyIterator::new()).rev().any(|i| i == 0));
-}
-
-#[test]
-fn test_rposition() {
- fn f(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'b' }
- fn g(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'd' }
- let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
-
- assert_eq!(v.iter().rposition(f), Some(3));
- assert!(v.iter().rposition(g).is_none());
-}
-
-#[test]
-#[should_panic]
-fn test_rposition_panic() {
- let v: [(Box<_>, Box<_>); 4] =
- [(box 0, box 0), (box 0, box 0),
- (box 0, box 0), (box 0, box 0)];
- let mut i = 0;
- v.iter().rposition(|_elt| {
- if i == 2 {
- panic!()
- }
- i += 1;
- false
- });
-}
-
-
-#[test]
-fn test_double_ended_flat_map() {
- let u = [0,1];
- let v = [5,6,7,8];
- let mut it = u.iter().flat_map(|x| &v[*x..v.len()]);
- assert_eq!(it.next_back().unwrap(), &8);
- assert_eq!(it.next().unwrap(), &5);
- assert_eq!(it.next_back().unwrap(), &7);
- assert_eq!(it.next_back().unwrap(), &6);
- assert_eq!(it.next_back().unwrap(), &8);
- assert_eq!(it.next().unwrap(), &6);
- assert_eq!(it.next_back().unwrap(), &7);
- assert_eq!(it.next_back(), None);
- assert_eq!(it.next(), None);
- assert_eq!(it.next_back(), None);
-}
-
-#[test]
-fn test_double_ended_range() {
- assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
- for _ in (10..0).rev() {
- panic!("unreachable");
- }
-
- assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
- for _ in (10..0).rev() {
- panic!("unreachable");
- }
-}
-
-#[test]
-fn test_range() {
- assert_eq!((0..5).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
- assert_eq!((-10..-1).collect::<Vec<_>>(), [-10, -9, -8, -7, -6, -5, -4, -3, -2]);
- assert_eq!((0..5).rev().collect::<Vec<_>>(), [4, 3, 2, 1, 0]);
- assert_eq!((200..-5).count(), 0);
- assert_eq!((200..-5).rev().count(), 0);
- assert_eq!((200..200).count(), 0);
- assert_eq!((200..200).rev().count(), 0);
-
- assert_eq!((0..100).size_hint(), (100, Some(100)));
- // this test is only meaningful when sizeof usize < sizeof u64
- assert_eq!((usize::MAX - 1..usize::MAX).size_hint(), (1, Some(1)));
- assert_eq!((-10..-1).size_hint(), (9, Some(9)));
- assert_eq!((-1..-10).size_hint(), (0, Some(0)));
-
- assert_eq!((-70..58).size_hint(), (128, Some(128)));
- assert_eq!((-128..127).size_hint(), (255, Some(255)));
- assert_eq!((-2..isize::MAX).size_hint(),
- (isize::MAX as usize + 2, Some(isize::MAX as usize + 2)));
-}
-
-#[test]
-fn test_range_step() {
- assert_eq!((0..20).step_by(5).collect::<Vec<isize>>(), [0, 5, 10, 15]);
- assert_eq!((20..0).step_by(-5).collect::<Vec<isize>>(), [20, 15, 10, 5]);
- assert_eq!((20..0).step_by(-6).collect::<Vec<isize>>(), [20, 14, 8, 2]);
- assert_eq!((200..255).step_by(50).collect::<Vec<u8>>(), [200, 250]);
- assert_eq!((200..-5).step_by(1).collect::<Vec<isize>>(), []);
- assert_eq!((200..200).step_by(1).collect::<Vec<isize>>(), []);
-
- assert_eq!((0..20).step_by(1).size_hint(), (20, Some(20)));
- assert_eq!((0..20).step_by(21).size_hint(), (1, Some(1)));
- assert_eq!((0..20).step_by(5).size_hint(), (4, Some(4)));
- assert_eq!((20..0).step_by(-5).size_hint(), (4, Some(4)));
- assert_eq!((20..0).step_by(-6).size_hint(), (4, Some(4)));
- assert_eq!((20..-5).step_by(1).size_hint(), (0, Some(0)));
- assert_eq!((20..20).step_by(1).size_hint(), (0, Some(0)));
- assert_eq!((0..1).step_by(0).size_hint(), (0, None));
- assert_eq!((i8::MAX..i8::MIN).step_by(i8::MIN).size_hint(), (2, Some(2)));
- assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX).size_hint(), (3, Some(3)));
- assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX)));
-}
-
-#[test]
-fn test_repeat() {
- let mut it = repeat(42);
- assert_eq!(it.next(), Some(42));
- assert_eq!(it.next(), Some(42));
- assert_eq!(it.next(), Some(42));
-}
-
-#[test]
-fn test_fuse() {
- let mut it = 0..3;
- assert_eq!(it.len(), 3);
- assert_eq!(it.next(), Some(0));
- assert_eq!(it.len(), 2);
- assert_eq!(it.next(), Some(1));
- assert_eq!(it.len(), 1);
- assert_eq!(it.next(), Some(2));
- assert_eq!(it.len(), 0);
- assert_eq!(it.next(), None);
- assert_eq!(it.len(), 0);
- assert_eq!(it.next(), None);
- assert_eq!(it.len(), 0);
- assert_eq!(it.next(), None);
- assert_eq!(it.len(), 0);
-}
-
-#[test]
-fn test_fuse_nth() {
- let xs = [0, 1, 2];
- let mut it = xs.iter();
-
- assert_eq!(it.len(), 3);
- assert_eq!(it.nth(2), Some(&2));
- assert_eq!(it.len(), 0);
- assert_eq!(it.nth(2), None);
- assert_eq!(it.len(), 0);
-}
-
-#[test]
-fn test_fuse_last() {
- let xs = [0, 1, 2];
- let it = xs.iter();
-
- assert_eq!(it.len(), 3);
- assert_eq!(it.last(), Some(&2));
-}
-
-#[test]
-fn test_fuse_count() {
- let xs = [0, 1, 2];
- let it = xs.iter();
-
- assert_eq!(it.len(), 3);
- assert_eq!(it.count(), 3);
- // Can't check len now because count consumes.
-}
-
-#[test]
-fn test_once() {
- let mut it = once(42);
- assert_eq!(it.next(), Some(42));
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_empty() {
- let mut it = empty::<i32>();
- assert_eq!(it.next(), None);
-}
-
-#[test]
-fn test_chain_fold() {
- let xs = [1, 2, 3];
- let ys = [1, 2, 0];
-
- let mut iter = xs.iter().chain(&ys);
- iter.next();
- let mut result = Vec::new();
- iter.fold((), |(), &elt| result.push(elt));
- assert_eq!(&[2, 3, 1, 2, 0], &result[..]);
-}
-
+++ /dev/null
-// Copyright 2014 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.
-
-#![deny(warnings)]
-
-#![feature(box_syntax)]
-#![feature(char_escape_debug)]
-#![feature(const_fn)]
-#![feature(core_private_bignum)]
-#![feature(core_private_diy_float)]
-#![feature(dec2flt)]
-#![feature(decode_utf8)]
-#![feature(fixed_size_array)]
-#![feature(flt2dec)]
-#![feature(fmt_internals)]
-#![feature(libc)]
-#![feature(nonzero)]
-#![feature(rand)]
-#![feature(raw)]
-#![feature(sip_hash_13)]
-#![feature(slice_patterns)]
-#![feature(sort_internals)]
-#![feature(sort_unstable)]
-#![feature(step_by)]
-#![feature(test)]
-#![feature(try_from)]
-#![feature(unicode)]
-#![feature(unique)]
-
-extern crate core;
-extern crate test;
-extern crate libc;
-extern crate std_unicode;
-extern crate rand;
-
-mod any;
-mod array;
-mod atomic;
-mod cell;
-mod char;
-mod clone;
-mod cmp;
-mod fmt;
-mod hash;
-mod intrinsics;
-mod iter;
-mod mem;
-mod nonzero;
-mod num;
-mod ops;
-mod option;
-mod ptr;
-mod result;
-mod slice;
-mod str;
-mod tuple;
+++ /dev/null
-// Copyright 2014-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.
-
-use core::mem::*;
-
-#[test]
-fn size_of_basic() {
- assert_eq!(size_of::<u8>(), 1);
- assert_eq!(size_of::<u16>(), 2);
- assert_eq!(size_of::<u32>(), 4);
- assert_eq!(size_of::<u64>(), 8);
-}
-
-#[test]
-#[cfg(target_pointer_width = "16")]
-fn size_of_16() {
- assert_eq!(size_of::<usize>(), 2);
- assert_eq!(size_of::<*const usize>(), 2);
-}
-
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn size_of_32() {
- assert_eq!(size_of::<usize>(), 4);
- assert_eq!(size_of::<*const usize>(), 4);
-}
-
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn size_of_64() {
- assert_eq!(size_of::<usize>(), 8);
- assert_eq!(size_of::<*const usize>(), 8);
-}
-
-#[test]
-fn size_of_val_basic() {
- assert_eq!(size_of_val(&1u8), 1);
- assert_eq!(size_of_val(&1u16), 2);
- assert_eq!(size_of_val(&1u32), 4);
- assert_eq!(size_of_val(&1u64), 8);
-}
-
-#[test]
-fn align_of_basic() {
- assert_eq!(align_of::<u8>(), 1);
- assert_eq!(align_of::<u16>(), 2);
- assert_eq!(align_of::<u32>(), 4);
-}
-
-#[test]
-#[cfg(target_pointer_width = "16")]
-fn align_of_16() {
- assert_eq!(align_of::<usize>(), 2);
- assert_eq!(align_of::<*const usize>(), 2);
-}
-
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn align_of_32() {
- assert_eq!(align_of::<usize>(), 4);
- assert_eq!(align_of::<*const usize>(), 4);
-}
-
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn align_of_64() {
- assert_eq!(align_of::<usize>(), 8);
- assert_eq!(align_of::<*const usize>(), 8);
-}
-
-#[test]
-fn align_of_val_basic() {
- assert_eq!(align_of_val(&1u8), 1);
- assert_eq!(align_of_val(&1u16), 2);
- assert_eq!(align_of_val(&1u32), 4);
-}
-
-#[test]
-fn test_swap() {
- let mut x = 31337;
- let mut y = 42;
- swap(&mut x, &mut y);
- assert_eq!(x, 42);
- assert_eq!(y, 31337);
-}
-
-#[test]
-fn test_replace() {
- let mut x = Some("test".to_string());
- let y = replace(&mut x, None);
- assert!(x.is_none());
- assert!(y.is_some());
-}
-
-#[test]
-fn test_transmute_copy() {
- assert_eq!(1, unsafe { transmute_copy(&1) });
-}
-
-#[test]
-fn test_transmute() {
- trait Foo { fn dummy(&self) { } }
- impl Foo for isize {}
-
- let a = box 100isize as Box<Foo>;
- unsafe {
- let x: ::core::raw::TraitObject = transmute(a);
- assert!(*(x.data as *const isize) == 100);
- let _x: Box<Foo> = transmute(x);
- }
-
- unsafe {
- assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
- }
-}
-
+++ /dev/null
-// Copyright 2012-2014 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.
-
-use core::nonzero::NonZero;
-use core::option::Option;
-use core::option::Option::{Some, None};
-use std::mem::size_of;
-
-#[test]
-fn test_create_nonzero_instance() {
- let _a = unsafe {
- NonZero::new(21)
- };
-}
-
-#[test]
-fn test_size_nonzero_in_option() {
- assert_eq!(size_of::<NonZero<u32>>(), size_of::<Option<NonZero<u32>>>());
-}
-
-#[test]
-fn test_match_on_nonzero_option() {
- let a = Some(unsafe {
- NonZero::new(42)
- });
- match a {
- Some(val) => assert_eq!(*val, 42),
- None => panic!("unexpected None while matching on Some(NonZero(_))")
- }
-
- match unsafe { Some(NonZero::new(43)) } {
- Some(val) => assert_eq!(*val, 43),
- None => panic!("unexpected None while matching on Some(NonZero(_))")
- }
-}
-
-#[test]
-fn test_match_option_empty_vec() {
- let a: Option<Vec<isize>> = Some(vec![]);
- match a {
- None => panic!("unexpected None while matching on Some(vec![])"),
- _ => {}
- }
-}
-
-#[test]
-fn test_match_option_vec() {
- let a = Some(vec![1, 2, 3, 4]);
- match a {
- Some(v) => assert_eq!(v, [1, 2, 3, 4]),
- None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])")
- }
-}
-
-#[test]
-fn test_match_option_rc() {
- use std::rc::Rc;
-
- let five = Rc::new(5);
- match Some(five) {
- Some(r) => assert_eq!(*r, 5),
- None => panic!("unexpected None while matching on Some(Rc::new(5))")
- }
-}
-
-#[test]
-fn test_match_option_arc() {
- use std::sync::Arc;
-
- let five = Arc::new(5);
- match Some(five) {
- Some(a) => assert_eq!(*a, 5),
- None => panic!("unexpected None while matching on Some(Arc::new(5))")
- }
-}
-
-#[test]
-fn test_match_option_empty_string() {
- let a = Some(String::new());
- match a {
- None => panic!("unexpected None while matching on Some(String::new())"),
- _ => {}
- }
-}
-
-#[test]
-fn test_match_option_string() {
- let five = "Five".to_string();
- match Some(five) {
- Some(s) => assert_eq!(s, "Five"),
- None => panic!("unexpected None while matching on Some(String { ... })")
- }
-}
+++ /dev/null
-// Copyright 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.
-
-use std::prelude::v1::*;
-use core::num::bignum::tests::Big8x3 as Big;
-
-#[test]
-#[should_panic]
-fn test_from_u64_overflow() {
- Big::from_u64(0x1000000);
-}
-
-#[test]
-fn test_add() {
- assert_eq!(*Big::from_small(3).add(&Big::from_small(4)), Big::from_small(7));
- assert_eq!(*Big::from_small(3).add(&Big::from_small(0)), Big::from_small(3));
- assert_eq!(*Big::from_small(0).add(&Big::from_small(3)), Big::from_small(3));
- assert_eq!(*Big::from_small(3).add(&Big::from_u64(0xfffe)), Big::from_u64(0x10001));
- assert_eq!(*Big::from_u64(0xfedc).add(&Big::from_u64(0x789)), Big::from_u64(0x10665));
- assert_eq!(*Big::from_u64(0x789).add(&Big::from_u64(0xfedc)), Big::from_u64(0x10665));
-}
-
-#[test]
-#[should_panic]
-fn test_add_overflow_1() {
- Big::from_small(1).add(&Big::from_u64(0xffffff));
-}
-
-#[test]
-#[should_panic]
-fn test_add_overflow_2() {
- Big::from_u64(0xffffff).add(&Big::from_small(1));
-}
-
-#[test]
-fn test_add_small() {
- assert_eq!(*Big::from_small(3).add_small(4), Big::from_small(7));
- assert_eq!(*Big::from_small(3).add_small(0), Big::from_small(3));
- assert_eq!(*Big::from_small(0).add_small(3), Big::from_small(3));
- assert_eq!(*Big::from_small(7).add_small(250), Big::from_u64(257));
- assert_eq!(*Big::from_u64(0x7fff).add_small(1), Big::from_u64(0x8000));
- assert_eq!(*Big::from_u64(0x2ffe).add_small(0x35), Big::from_u64(0x3033));
- assert_eq!(*Big::from_small(0xdc).add_small(0x89), Big::from_u64(0x165));
-}
-
-#[test]
-#[should_panic]
-fn test_add_small_overflow() {
- Big::from_u64(0xffffff).add_small(1);
-}
-
-#[test]
-fn test_sub() {
- assert_eq!(*Big::from_small(7).sub(&Big::from_small(4)), Big::from_small(3));
- assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x789)), Big::from_u64(0xfedc));
- assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0xfedc)), Big::from_u64(0x789));
- assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10664)), Big::from_small(1));
- assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10665)), Big::from_small(0));
-}
-
-#[test]
-#[should_panic]
-fn test_sub_underflow_1() {
- Big::from_u64(0x10665).sub(&Big::from_u64(0x10666));
-}
-
-#[test]
-#[should_panic]
-fn test_sub_underflow_2() {
- Big::from_small(0).sub(&Big::from_u64(0x123456));
-}
-
-#[test]
-fn test_mul_small() {
- assert_eq!(*Big::from_small(7).mul_small(5), Big::from_small(35));
- assert_eq!(*Big::from_small(0xff).mul_small(0xff), Big::from_u64(0xfe01));
- assert_eq!(*Big::from_u64(0xffffff/13).mul_small(13), Big::from_u64(0xffffff));
-}
-
-#[test]
-#[should_panic]
-fn test_mul_small_overflow() {
- Big::from_u64(0x800000).mul_small(2);
-}
-
-#[test]
-fn test_mul_pow2() {
- assert_eq!(*Big::from_small(0x7).mul_pow2(4), Big::from_small(0x70));
- assert_eq!(*Big::from_small(0xff).mul_pow2(1), Big::from_u64(0x1fe));
- assert_eq!(*Big::from_small(0xff).mul_pow2(12), Big::from_u64(0xff000));
- assert_eq!(*Big::from_small(0x1).mul_pow2(23), Big::from_u64(0x800000));
- assert_eq!(*Big::from_u64(0x123).mul_pow2(0), Big::from_u64(0x123));
- assert_eq!(*Big::from_u64(0x123).mul_pow2(7), Big::from_u64(0x9180));
- assert_eq!(*Big::from_u64(0x123).mul_pow2(15), Big::from_u64(0x918000));
- assert_eq!(*Big::from_small(0).mul_pow2(23), Big::from_small(0));
-}
-
-#[test]
-#[should_panic]
-fn test_mul_pow2_overflow_1() {
- Big::from_u64(0x1).mul_pow2(24);
-}
-
-#[test]
-#[should_panic]
-fn test_mul_pow2_overflow_2() {
- Big::from_u64(0x123).mul_pow2(16);
-}
-
-#[test]
-fn test_mul_pow5() {
- assert_eq!(*Big::from_small(42).mul_pow5(0), Big::from_small(42));
- assert_eq!(*Big::from_small(1).mul_pow5(2), Big::from_small(25));
- assert_eq!(*Big::from_small(1).mul_pow5(4), Big::from_u64(25 * 25));
- assert_eq!(*Big::from_small(4).mul_pow5(3), Big::from_u64(500));
- assert_eq!(*Big::from_small(140).mul_pow5(2), Big::from_u64(25 * 140));
- assert_eq!(*Big::from_small(25).mul_pow5(1), Big::from_small(125));
- assert_eq!(*Big::from_small(125).mul_pow5(7), Big::from_u64(9765625));
- assert_eq!(*Big::from_small(0).mul_pow5(127), Big::from_small(0));
-}
-
-#[test]
-#[should_panic]
-fn test_mul_pow5_overflow_1() {
- Big::from_small(1).mul_pow5(12);
-}
-
-#[test]
-#[should_panic]
-fn test_mul_pow5_overflow_2() {
- Big::from_small(230).mul_pow5(8);
-}
-
-#[test]
-fn test_mul_digits() {
- assert_eq!(*Big::from_small(3).mul_digits(&[5]), Big::from_small(15));
- assert_eq!(*Big::from_small(0xff).mul_digits(&[0xff]), Big::from_u64(0xfe01));
- assert_eq!(*Big::from_u64(0x123).mul_digits(&[0x56, 0x4]), Big::from_u64(0x4edc2));
- assert_eq!(*Big::from_u64(0x12345).mul_digits(&[0x67]), Big::from_u64(0x7530c3));
- assert_eq!(*Big::from_small(0x12).mul_digits(&[0x67, 0x45, 0x3]), Big::from_u64(0x3ae13e));
- assert_eq!(*Big::from_u64(0xffffff/13).mul_digits(&[13]), Big::from_u64(0xffffff));
- assert_eq!(*Big::from_small(13).mul_digits(&[0x3b, 0xb1, 0x13]), Big::from_u64(0xffffff));
-}
-
-#[test]
-#[should_panic]
-fn test_mul_digits_overflow_1() {
- Big::from_u64(0x800000).mul_digits(&[2]);
-}
-
-#[test]
-#[should_panic]
-fn test_mul_digits_overflow_2() {
- Big::from_u64(0x1000).mul_digits(&[0, 0x10]);
-}
-
-#[test]
-fn test_div_rem_small() {
- let as_val = |(q, r): (&mut Big, u8)| (q.clone(), r);
- assert_eq!(as_val(Big::from_small(0xff).div_rem_small(15)), (Big::from_small(17), 0));
- assert_eq!(as_val(Big::from_small(0xff).div_rem_small(16)), (Big::from_small(15), 15));
- assert_eq!(as_val(Big::from_small(3).div_rem_small(40)), (Big::from_small(0), 3));
- assert_eq!(as_val(Big::from_u64(0xffffff).div_rem_small(123)),
- (Big::from_u64(0xffffff / 123), (0xffffffu64 % 123) as u8));
- assert_eq!(as_val(Big::from_u64(0x10000).div_rem_small(123)),
- (Big::from_u64(0x10000 / 123), (0x10000u64 % 123) as u8));
-}
-
-#[test]
-fn test_div_rem() {
- fn div_rem(n: u64, d: u64) -> (Big, Big) {
- let mut q = Big::from_small(42);
- let mut r = Big::from_small(42);
- Big::from_u64(n).div_rem(&Big::from_u64(d), &mut q, &mut r);
- (q, r)
- }
- assert_eq!(div_rem(1, 1), (Big::from_small(1), Big::from_small(0)));
- assert_eq!(div_rem(4, 3), (Big::from_small(1), Big::from_small(1)));
- assert_eq!(div_rem(1, 7), (Big::from_small(0), Big::from_small(1)));
- assert_eq!(div_rem(45, 9), (Big::from_small(5), Big::from_small(0)));
- assert_eq!(div_rem(103, 9), (Big::from_small(11), Big::from_small(4)));
- assert_eq!(div_rem(123456, 77), (Big::from_u64(1603), Big::from_small(25)));
- assert_eq!(div_rem(0xffff, 1), (Big::from_u64(0xffff), Big::from_small(0)));
- assert_eq!(div_rem(0xeeee, 0xffff), (Big::from_small(0), Big::from_u64(0xeeee)));
- assert_eq!(div_rem(2_000_000, 2), (Big::from_u64(1_000_000), Big::from_u64(0)));
-}
-
-#[test]
-fn test_is_zero() {
- assert!(Big::from_small(0).is_zero());
- assert!(!Big::from_small(3).is_zero());
- assert!(!Big::from_u64(0x123).is_zero());
- assert!(!Big::from_u64(0xffffff).sub(&Big::from_u64(0xfffffe)).is_zero());
- assert!(Big::from_u64(0xffffff).sub(&Big::from_u64(0xffffff)).is_zero());
-}
-
-#[test]
-fn test_get_bit() {
- let x = Big::from_small(0b1101);
- assert_eq!(x.get_bit(0), 1);
- assert_eq!(x.get_bit(1), 0);
- assert_eq!(x.get_bit(2), 1);
- assert_eq!(x.get_bit(3), 1);
- let y = Big::from_u64(1 << 15);
- assert_eq!(y.get_bit(14), 0);
- assert_eq!(y.get_bit(15), 1);
- assert_eq!(y.get_bit(16), 0);
-}
-
-#[test]
-#[should_panic]
-fn test_get_bit_out_of_range() {
- Big::from_small(42).get_bit(24);
-}
-
-#[test]
-fn test_bit_length() {
- assert_eq!(Big::from_small(0).bit_length(), 0);
- assert_eq!(Big::from_small(1).bit_length(), 1);
- assert_eq!(Big::from_small(5).bit_length(), 3);
- assert_eq!(Big::from_small(0x18).bit_length(), 5);
- assert_eq!(Big::from_u64(0x4073).bit_length(), 15);
- assert_eq!(Big::from_u64(0xffffff).bit_length(), 24);
-}
-
-#[test]
-fn test_ord() {
- assert!(Big::from_u64(0) < Big::from_u64(0xffffff));
- assert!(Big::from_u64(0x102) < Big::from_u64(0x201));
-}
-
-#[test]
-fn test_fmt() {
- assert_eq!(format!("{:?}", Big::from_u64(0)), "0x0");
- assert_eq!(format!("{:?}", Big::from_u64(0x1)), "0x1");
- assert_eq!(format!("{:?}", Big::from_u64(0x12)), "0x12");
- assert_eq!(format!("{:?}", Big::from_u64(0x123)), "0x1_23");
- assert_eq!(format!("{:?}", Big::from_u64(0x1234)), "0x12_34");
- assert_eq!(format!("{:?}", Big::from_u64(0x12345)), "0x1_23_45");
- assert_eq!(format!("{:?}", Big::from_u64(0x123456)), "0x12_34_56");
-}
-
+++ /dev/null
-// Copyright 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.
-
-#![allow(overflowing_literals)]
-
-use std::{i64, f32, f64};
-
-mod parse;
-mod rawfp;
-
-// Take a float literal, turn it into a string in various ways (that are all trusted
-// to be correct) and see if those strings are parsed back to the value of the literal.
-// Requires a *polymorphic literal*, i.e. one that can serve as f64 as well as f32.
-macro_rules! test_literal {
- ($x: expr) => ({
- let x32: f32 = $x;
- let x64: f64 = $x;
- let inputs = &[stringify!($x).into(), format!("{:?}", x64), format!("{:e}", x64)];
- for input in inputs {
- assert_eq!(input.parse(), Ok(x64));
- assert_eq!(input.parse(), Ok(x32));
- let neg_input = &format!("-{}", input);
- assert_eq!(neg_input.parse(), Ok(-x64));
- assert_eq!(neg_input.parse(), Ok(-x32));
- }
- })
-}
-
-#[test]
-fn ordinary() {
- test_literal!(1.0);
- test_literal!(3e-5);
- test_literal!(0.1);
- test_literal!(12345.);
- test_literal!(0.9999999);
- test_literal!(2.2250738585072014e-308);
-}
-
-#[test]
-fn special_code_paths() {
- test_literal!(36893488147419103229.0); // 2^65 - 3, triggers half-to-even with even significand
- test_literal!(101e-33); // Triggers the tricky underflow case in AlgorithmM (for f32)
- test_literal!(1e23); // Triggers AlgorithmR
- test_literal!(2075e23); // Triggers another path through AlgorithmR
- test_literal!(8713e-23); // ... and yet another.
-}
-
-#[test]
-fn large() {
- test_literal!(1e300);
- test_literal!(123456789.34567e250);
- test_literal!(943794359898089732078308743689303290943794359843568973207830874368930329.);
-}
-
-#[test]
-fn subnormals() {
- test_literal!(5e-324);
- test_literal!(91e-324);
- test_literal!(1e-322);
- test_literal!(13245643e-320);
- test_literal!(2.22507385851e-308);
- test_literal!(2.1e-308);
- test_literal!(4.9406564584124654e-324);
-}
-
-#[test]
-fn infinity() {
- test_literal!(1e400);
- test_literal!(1e309);
- test_literal!(2e308);
- test_literal!(1.7976931348624e308);
-}
-
-#[test]
-fn zero() {
- test_literal!(0.0);
- test_literal!(1e-325);
- test_literal!(1e-326);
- test_literal!(1e-500);
-}
-
-#[test]
-fn fast_path_correct() {
- // This number triggers the fast path and is handled incorrectly when compiling on
- // x86 without SSE2 (i.e., using the x87 FPU stack).
- test_literal!(1.448997445238699);
-}
-
-#[test]
-fn lonely_dot() {
- assert!(".".parse::<f32>().is_err());
- assert!(".".parse::<f64>().is_err());
-}
-
-#[test]
-fn lonely_sign() {
- assert!("+".parse::<f32>().is_err());
- assert!("-".parse::<f64>().is_err());
-}
-
-#[test]
-fn whitespace() {
- assert!(" 1.0".parse::<f32>().is_err());
- assert!("1.0 ".parse::<f64>().is_err());
-}
-
-#[test]
-fn nan() {
- assert!("NaN".parse::<f32>().unwrap().is_nan());
- assert!("NaN".parse::<f64>().unwrap().is_nan());
-}
-
-#[test]
-fn inf() {
- assert_eq!("inf".parse(), Ok(f64::INFINITY));
- assert_eq!("-inf".parse(), Ok(f64::NEG_INFINITY));
- assert_eq!("inf".parse(), Ok(f32::INFINITY));
- assert_eq!("-inf".parse(), Ok(f32::NEG_INFINITY));
-}
-
-#[test]
-fn massive_exponent() {
- let max = i64::MAX;
- assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
- assert_eq!(format!("1e-{}000", max).parse(), Ok(0.0));
- assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
-}
-
-#[test]
-fn borderline_overflow() {
- let mut s = "0.".to_string();
- for _ in 0..375 {
- s.push('3');
- }
- // At the time of this writing, this returns Err(..), but this is a bug that should be fixed.
- // It makes no sense to enshrine that in a test, the important part is that it doesn't panic.
- let _ = s.parse::<f64>();
-}
+++ /dev/null
-// Copyright 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.
-
-use std::iter;
-use core::num::dec2flt::parse::{Decimal, parse_decimal};
-use core::num::dec2flt::parse::ParseResult::{Valid, Invalid};
-
-#[test]
-fn missing_pieces() {
- let permutations = &[".e", "1e", "e4", "e", ".12e", "321.e", "32.12e+", "12.32e-"];
- for &s in permutations {
- assert_eq!(parse_decimal(s), Invalid);
- }
-}
-
-#[test]
-fn invalid_chars() {
- let invalid = "r,?<j";
- let valid_strings = &["123", "666.", ".1", "5e1", "7e-3", "0.0e+1"];
- for c in invalid.chars() {
- for s in valid_strings {
- for i in 0..s.len() {
- let mut input = String::new();
- input.push_str(s);
- input.insert(i, c);
- assert!(parse_decimal(&input) == Invalid, "did not reject invalid {:?}", input);
- }
- }
- }
-}
-
-#[test]
-fn valid() {
- assert_eq!(parse_decimal("123.456e789"), Valid(Decimal::new(b"123", b"456", 789)));
- assert_eq!(parse_decimal("123.456e+789"), Valid(Decimal::new(b"123", b"456", 789)));
- assert_eq!(parse_decimal("123.456e-789"), Valid(Decimal::new(b"123", b"456", -789)));
- assert_eq!(parse_decimal(".050"), Valid(Decimal::new(b"", b"050", 0)));
- assert_eq!(parse_decimal("999"), Valid(Decimal::new(b"999", b"", 0)));
- assert_eq!(parse_decimal("1.e300"), Valid(Decimal::new(b"1", b"", 300)));
- assert_eq!(parse_decimal(".1e300"), Valid(Decimal::new(b"", b"1", 300)));
- assert_eq!(parse_decimal("101e-33"), Valid(Decimal::new(b"101", b"", -33)));
- let zeros: String = iter::repeat('0').take(25).collect();
- let s = format!("1.5e{}", zeros);
- assert_eq!(parse_decimal(&s), Valid(Decimal::new(b"1", b"5", 0)));
-}
+++ /dev/null
-// Copyright 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.
-
-use std::f64;
-use std::mem;
-use core::num::diy_float::Fp;
-use core::num::dec2flt::rawfp::{fp_to_float, prev_float, next_float, round_normal};
-
-fn integer_decode(f: f64) -> (u64, i16, i8) {
- let bits: u64 = unsafe { mem::transmute(f) };
- let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
- let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
- let mantissa = if exponent == 0 {
- (bits & 0xfffffffffffff) << 1
- } else {
- (bits & 0xfffffffffffff) | 0x10000000000000
- };
- // Exponent bias + mantissa shift
- exponent -= 1023 + 52;
- (mantissa, exponent, sign)
-}
-
-#[test]
-fn fp_to_float_half_to_even() {
- fn is_normalized(sig: u64) -> bool {
- // intentionally written without {min,max}_sig() as a sanity check
- sig >> 52 == 1 && sig >> 53 == 0
- }
-
- fn conv(sig: u64) -> u64 {
- // The significands are perfectly in range, so the exponent should not matter
- let (m1, e1, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 0 }));
- assert_eq!(e1, 0 + 64 - 53);
- let (m2, e2, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 55 }));
- assert_eq!(e2, 55 + 64 - 53);
- assert_eq!(m2, m1);
- let (m3, e3, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: -78 }));
- assert_eq!(e3, -78 + 64 - 53);
- assert_eq!(m3, m2);
- m3
- }
-
- let odd = 0x1F_EDCB_A012_345F;
- let even = odd - 1;
- assert!(is_normalized(odd));
- assert!(is_normalized(even));
- assert_eq!(conv(odd << 11), odd);
- assert_eq!(conv(even << 11), even);
- assert_eq!(conv(odd << 11 | 1 << 10), odd + 1);
- assert_eq!(conv(even << 11 | 1 << 10), even);
- assert_eq!(conv(even << 11 | 1 << 10 | 1), even + 1);
- assert_eq!(conv(odd << 11 | 1 << 9), odd);
- assert_eq!(conv(even << 11 | 1 << 9), even);
- assert_eq!(conv(odd << 11 | 0x7FF), odd + 1);
- assert_eq!(conv(even << 11 | 0x7FF), even + 1);
- assert_eq!(conv(odd << 11 | 0x3FF), odd);
- assert_eq!(conv(even << 11 | 0x3FF), even);
-}
-
-#[test]
-fn integers_to_f64() {
- assert_eq!(fp_to_float::<f64>(Fp { f: 1, e: 0 }), 1.0);
- assert_eq!(fp_to_float::<f64>(Fp { f: 42, e: 7 }), (42 << 7) as f64);
- assert_eq!(fp_to_float::<f64>(Fp { f: 1 << 20, e: 30 }), (1u64 << 50) as f64);
- assert_eq!(fp_to_float::<f64>(Fp { f: 4, e: -3 }), 0.5);
-}
-
-const SOME_FLOATS: [f64; 9] =
- [0.1f64, 33.568, 42.1e-5, 777.0e9, 1.1111, 0.347997,
- 9843579834.35892, 12456.0e-150, 54389573.0e-150];
-
-
-#[test]
-fn human_f64_roundtrip() {
- for &x in &SOME_FLOATS {
- let (f, e, _) = integer_decode(x);
- let fp = Fp { f: f, e: e};
- assert_eq!(fp_to_float::<f64>(fp), x);
- }
-}
-
-#[test]
-fn rounding_overflow() {
- let x = Fp { f: 0xFF_FF_FF_FF_FF_FF_FF_00u64, e: 42 };
- let rounded = round_normal::<f64>(x);
- let adjusted_k = x.e + 64 - 53;
- assert_eq!(rounded.sig, 1 << 52);
- assert_eq!(rounded.k, adjusted_k + 1);
-}
-
-#[test]
-fn prev_float_monotonic() {
- let mut x = 1.0;
- for _ in 0..100 {
- let x1 = prev_float(x);
- assert!(x1 < x);
- assert!(x - x1 < 1e-15);
- x = x1;
- }
-}
-
-const MIN_SUBNORMAL: f64 = 5e-324;
-
-#[test]
-fn next_float_zero() {
- let tiny = next_float(0.0);
- assert_eq!(tiny, MIN_SUBNORMAL);
- assert!(tiny != 0.0);
-}
-
-#[test]
-fn next_float_subnormal() {
- let second = next_float(MIN_SUBNORMAL);
- // For subnormals, MIN_SUBNORMAL is the ULP
- assert!(second != MIN_SUBNORMAL);
- assert!(second > 0.0);
- assert_eq!(second - MIN_SUBNORMAL, MIN_SUBNORMAL);
-}
-
-#[test]
-fn next_float_inf() {
- assert_eq!(next_float(f64::MAX), f64::INFINITY);
- assert_eq!(next_float(f64::INFINITY), f64::INFINITY);
-}
-
-#[test]
-fn next_prev_identity() {
- for &x in &SOME_FLOATS {
- assert_eq!(prev_float(next_float(x)), x);
- assert_eq!(prev_float(prev_float(next_float(next_float(x)))), x);
- assert_eq!(next_float(prev_float(x)), x);
- assert_eq!(next_float(next_float(prev_float(prev_float(x)))), x);
- }
-}
-
-#[test]
-fn next_float_monotonic() {
- let mut x = 0.49999999999999;
- assert!(x < 0.5);
- for _ in 0..200 {
- let x1 = next_float(x);
- assert!(x1 > x);
- assert!(x1 - x < 1e-15, "next_float_monotonic: delta = {:?}", x1 - x);
- x = x1;
- }
- assert!(x > 0.5);
-}
+++ /dev/null
-// Copyright 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.
-
-// FIXME https://github.com/kripken/emscripten/issues/4563
-// NB we have to actually not compile this test to avoid
-// an undefined symbol error
-#![cfg(not(target_os = "emscripten"))]
-
-use core::num::flt2dec::estimator::*;
-
-#[test]
-fn test_estimate_scaling_factor() {
- macro_rules! assert_almost_eq {
- ($actual:expr, $expected:expr) => ({
- let actual = $actual;
- let expected = $expected;
- println!("{} - {} = {} - {} = {}", stringify!($expected), stringify!($actual),
- expected, actual, expected - actual);
- assert!(expected == actual || expected == actual + 1,
- "expected {}, actual {}", expected, actual);
- })
- }
-
- assert_almost_eq!(estimate_scaling_factor(1, 0), 0);
- assert_almost_eq!(estimate_scaling_factor(2, 0), 1);
- assert_almost_eq!(estimate_scaling_factor(10, 0), 1);
- assert_almost_eq!(estimate_scaling_factor(11, 0), 2);
- assert_almost_eq!(estimate_scaling_factor(100, 0), 2);
- assert_almost_eq!(estimate_scaling_factor(101, 0), 3);
- assert_almost_eq!(estimate_scaling_factor(10000000000000000000, 0), 19);
- assert_almost_eq!(estimate_scaling_factor(10000000000000000001, 0), 20);
-
- // 1/2^20 = 0.00000095367...
- assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000, -20), -6);
- assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000 + 1, -20), -5);
- assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000, -20), -5);
- assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000 + 1, -20), -4);
- assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000, -20), -4);
- assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000 + 1, -20), -3);
- assert_almost_eq!(estimate_scaling_factor(1048575, -20), 0);
- assert_almost_eq!(estimate_scaling_factor(1048576, -20), 0);
- assert_almost_eq!(estimate_scaling_factor(1048577, -20), 1);
- assert_almost_eq!(estimate_scaling_factor(10485759999999999999, -20), 13);
- assert_almost_eq!(estimate_scaling_factor(10485760000000000000, -20), 13);
- assert_almost_eq!(estimate_scaling_factor(10485760000000000001, -20), 14);
-
- // extreme values:
- // 2^-1074 = 4.94065... * 10^-324
- // (2^53-1) * 2^971 = 1.79763... * 10^308
- assert_almost_eq!(estimate_scaling_factor(1, -1074), -323);
- assert_almost_eq!(estimate_scaling_factor(0x1fffffffffffff, 971), 309);
-
- for i in -1074..972 {
- let expected = super::ldexp_f64(1.0, i).log10().ceil();
- assert_almost_eq!(estimate_scaling_factor(1, i as i16), expected as i16);
- }
-}
-
+++ /dev/null
-// Copyright 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.
-
-use std::prelude::v1::*;
-use std::{str, mem, i16, f32, f64, fmt};
-use std::__rand as rand;
-use rand::{Rand, XorShiftRng};
-use rand::distributions::{IndependentSample, Range};
-
-use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
-use core::num::flt2dec::{MAX_SIG_DIGITS, round_up, Part, Formatted, Sign};
-use core::num::flt2dec::{to_shortest_str, to_shortest_exp_str,
- to_exact_exp_str, to_exact_fixed_str};
-
-pub use test::Bencher;
-
-mod estimator;
-mod strategy {
- mod dragon;
- mod grisu;
-}
-
-pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
- match decode(v).1 {
- FullDecoded::Finite(decoded) => decoded,
- full_decoded => panic!("expected finite, got {:?} instead", full_decoded)
- }
-}
-
-macro_rules! check_shortest {
- ($f:ident($v:expr) => $buf:expr, $exp:expr) => (
- check_shortest!($f($v) => $buf, $exp;
- "shortest mismatch for v={v}: actual {actual:?}, expected {expected:?}",
- v = stringify!($v))
- );
-
- ($f:ident{$($k:ident: $v:expr),+} => $buf:expr, $exp:expr) => (
- check_shortest!($f{$($k: $v),+} => $buf, $exp;
- "shortest mismatch for {v:?}: actual {actual:?}, expected {expected:?}",
- v = Decoded { $($k: $v),+ })
- );
-
- ($f:ident($v:expr) => $buf:expr, $exp:expr; $fmt:expr, $($key:ident = $val:expr),*) => ({
- let mut buf = [b'_'; MAX_SIG_DIGITS];
- let (len, k) = $f(&decode_finite($v), &mut buf);
- assert!((&buf[..len], k) == ($buf, $exp),
- $fmt, actual = (str::from_utf8(&buf[..len]).unwrap(), k),
- expected = (str::from_utf8($buf).unwrap(), $exp),
- $($key = $val),*);
- });
-
- ($f:ident{$($k:ident: $v:expr),+} => $buf:expr, $exp:expr;
- $fmt:expr, $($key:ident = $val:expr),*) => ({
- let mut buf = [b'_'; MAX_SIG_DIGITS];
- let (len, k) = $f(&Decoded { $($k: $v),+ }, &mut buf);
- assert!((&buf[..len], k) == ($buf, $exp),
- $fmt, actual = (str::from_utf8(&buf[..len]).unwrap(), k),
- expected = (str::from_utf8($buf).unwrap(), $exp),
- $($key = $val),*);
- })
-}
-
-macro_rules! try_exact {
- ($f:ident($decoded:expr) => $buf:expr, $expected:expr, $expectedk:expr;
- $fmt:expr, $($key:ident = $val:expr),*) => ({
- let (len, k) = $f($decoded, &mut $buf[..$expected.len()], i16::MIN);
- assert!((&$buf[..len], k) == ($expected, $expectedk),
- $fmt, actual = (str::from_utf8(&$buf[..len]).unwrap(), k),
- expected = (str::from_utf8($expected).unwrap(), $expectedk),
- $($key = $val),*);
- })
-}
-
-macro_rules! try_fixed {
- ($f:ident($decoded:expr) => $buf:expr, $request:expr, $expected:expr, $expectedk:expr;
- $fmt:expr, $($key:ident = $val:expr),*) => ({
- let (len, k) = $f($decoded, &mut $buf[..], $request);
- assert!((&$buf[..len], k) == ($expected, $expectedk),
- $fmt, actual = (str::from_utf8(&$buf[..len]).unwrap(), k),
- expected = (str::from_utf8($expected).unwrap(), $expectedk),
- $($key = $val),*);
- })
-}
-
-fn ldexp_f32(a: f32, b: i32) -> f32 {
- ldexp_f64(a as f64, b) as f32
-}
-
-fn ldexp_f64(a: f64, b: i32) -> f64 {
- extern {
- fn ldexp(x: f64, n: i32) -> f64;
- }
- unsafe { ldexp(a, b) }
-}
-
-fn check_exact<F, T>(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16)
- where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
- // use a large enough buffer
- let mut buf = [b'_'; 1024];
- let mut expected_ = [b'_'; 1024];
-
- let decoded = decode_finite(v);
- let cut = expected.iter().position(|&c| c == b' ');
-
- // check significant digits
- for i in 1..cut.unwrap_or(expected.len() - 1) {
- expected_[..i].copy_from_slice(&expected[..i]);
- let mut expectedk_ = expectedk;
- if expected[i] >= b'5' {
- // check if this is a rounding-to-even case.
- // we avoid rounding ...x5000... (with infinite zeroes) to ...(x+1) when x is even.
- if !(i+1 < expected.len() && expected[i-1] & 1 == 0 &&
- expected[i] == b'5' &&
- expected[i+1] == b' ') {
- // if this returns true, expected_[..i] is all `9`s and being rounded up.
- // we should always return `100..00` (`i` digits) instead, since that's
- // what we can came up with `i` digits anyway. `round_up` assumes that
- // the adjustment to the length is done by caller, which we simply ignore.
- if let Some(_) = round_up(&mut expected_, i) { expectedk_ += 1; }
- }
- }
-
- try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk_;
- "exact sigdigit mismatch for v={v}, i={i}: \
- actual {actual:?}, expected {expected:?}",
- v = vstr, i = i);
- try_fixed!(f(&decoded) => &mut buf, expectedk_ - i as i16, &expected_[..i], expectedk_;
- "fixed sigdigit mismatch for v={v}, i={i}: \
- actual {actual:?}, expected {expected:?}",
- v = vstr, i = i);
- }
-
- // check exact rounding for zero- and negative-width cases
- let start;
- if expected[0] >= b'5' {
- try_fixed!(f(&decoded) => &mut buf, expectedk, b"1", expectedk + 1;
- "zero-width rounding-up mismatch for v={v}: \
- actual {actual:?}, expected {expected:?}",
- v = vstr);
- start = 1;
- } else {
- start = 0;
- }
- for i in start..-10 {
- try_fixed!(f(&decoded) => &mut buf, expectedk - i, b"", expectedk;
- "rounding-down mismatch for v={v}, i={i}: \
- actual {actual:?}, expected {expected:?}",
- v = vstr, i = -i);
- }
-
- // check infinite zero digits
- if let Some(cut) = cut {
- for i in cut..expected.len()-1 {
- expected_[..cut].copy_from_slice(&expected[..cut]);
- for c in &mut expected_[cut..i] { *c = b'0'; }
-
- try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk;
- "exact infzero mismatch for v={v}, i={i}: \
- actual {actual:?}, expected {expected:?}",
- v = vstr, i = i);
- try_fixed!(f(&decoded) => &mut buf, expectedk - i as i16, &expected_[..i], expectedk;
- "fixed infzero mismatch for v={v}, i={i}: \
- actual {actual:?}, expected {expected:?}",
- v = vstr, i = i);
- }
- }
-}
-
-trait TestableFloat : DecodableFloat + fmt::Display {
- /// Returns `x * 2^exp`. Almost same to `std::{f32,f64}::ldexp`.
- /// This is used for testing.
- fn ldexpi(f: i64, exp: isize) -> Self;
-}
-
-impl TestableFloat for f32 {
- fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() }
-}
-
-impl TestableFloat for f64 {
- fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() }
-}
-
-fn check_exact_one<F, T>(mut f: F, x: i64, e: isize, tstr: &str, expected: &[u8], expectedk: i16)
- where T: TestableFloat,
- F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
- // use a large enough buffer
- let mut buf = [b'_'; 1024];
- let v: T = TestableFloat::ldexpi(x, e);
- let decoded = decode_finite(v);
-
- try_exact!(f(&decoded) => &mut buf, &expected, expectedk;
- "exact mismatch for v={x}p{e}{t}: actual {actual:?}, expected {expected:?}",
- x = x, e = e, t = tstr);
- try_fixed!(f(&decoded) => &mut buf, expectedk - expected.len() as i16, &expected, expectedk;
- "fixed mismatch for v={x}p{e}{t}: actual {actual:?}, expected {expected:?}",
- x = x, e = e, t = tstr);
-}
-
-macro_rules! check_exact {
- ($f:ident($v:expr) => $buf:expr, $exp:expr) => (
- check_exact(|d,b,k| $f(d,b,k), $v, stringify!($v), $buf, $exp)
- )
-}
-
-macro_rules! check_exact_one {
- ($f:ident($x:expr, $e:expr; $t:ty) => $buf:expr, $exp:expr) => (
- check_exact_one::<_, $t>(|d,b,k| $f(d,b,k), $x, $e, stringify!($t), $buf, $exp)
- )
-}
-
-// in the following comments, three numbers are spaced by 1 ulp apart,
-// and the second one is being formatted.
-//
-// some tests are derived from [1].
-//
-// [1] Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion
-// ftp://ftp.ee.lbl.gov/testbase-report.ps.Z
-
-pub fn f32_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
- // 0.0999999940395355224609375
- // 0.100000001490116119384765625
- // 0.10000000894069671630859375
- check_shortest!(f(0.1f32) => b"1", 0);
-
- // 0.333333313465118408203125
- // 0.3333333432674407958984375 (1/3 in the default rounding)
- // 0.33333337306976318359375
- check_shortest!(f(1.0f32/3.0) => b"33333334", 0);
-
- // 10^1 * 0.31415917873382568359375
- // 10^1 * 0.31415920257568359375
- // 10^1 * 0.31415922641754150390625
- check_shortest!(f(3.141592f32) => b"3141592", 1);
-
- // 10^18 * 0.31415916243714048
- // 10^18 * 0.314159196796878848
- // 10^18 * 0.314159231156617216
- check_shortest!(f(3.141592e17f32) => b"3141592", 18);
-
- // regression test for decoders
- // 10^8 * 0.3355443
- // 10^8 * 0.33554432
- // 10^8 * 0.33554436
- check_shortest!(f(ldexp_f32(1.0, 25)) => b"33554432", 8);
-
- // 10^39 * 0.340282326356119256160033759537265639424
- // 10^39 * 0.34028234663852885981170418348451692544
- // 10^39 * 0.340282366920938463463374607431768211456
- check_shortest!(f(f32::MAX) => b"34028235", 39);
-
- // 10^-37 * 0.1175494210692441075487029444849287348827...
- // 10^-37 * 0.1175494350822287507968736537222245677818...
- // 10^-37 * 0.1175494490952133940450443629595204006810...
- check_shortest!(f(f32::MIN_POSITIVE) => b"11754944", -37);
-
- // 10^-44 * 0
- // 10^-44 * 0.1401298464324817070923729583289916131280...
- // 10^-44 * 0.2802596928649634141847459166579832262560...
- let minf32 = ldexp_f32(1.0, -149);
- check_shortest!(f(minf32) => b"1", -44);
-}
-
-pub fn f32_exact_sanity_test<F>(mut f: F)
- where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
- let minf32 = ldexp_f32(1.0, -149);
-
- check_exact!(f(0.1f32) => b"100000001490116119384765625 ", 0);
- check_exact!(f(0.5f32) => b"5 ", 0);
- check_exact!(f(1.0f32/3.0) => b"3333333432674407958984375 ", 0);
- check_exact!(f(3.141592f32) => b"31415920257568359375 ", 1);
- check_exact!(f(3.141592e17f32) => b"314159196796878848 ", 18);
- check_exact!(f(f32::MAX) => b"34028234663852885981170418348451692544 ", 39);
- check_exact!(f(f32::MIN_POSITIVE) => b"1175494350822287507968736537222245677818", -37);
- check_exact!(f(minf32) => b"1401298464324817070923729583289916131280", -44);
-
- // [1], Table 16: Stress Inputs for Converting 24-bit Binary to Decimal, < 1/2 ULP
- check_exact_one!(f(12676506, -102; f32) => b"2", -23);
- check_exact_one!(f(12676506, -103; f32) => b"12", -23);
- check_exact_one!(f(15445013, 86; f32) => b"119", 34);
- check_exact_one!(f(13734123, -138; f32) => b"3941", -34);
- check_exact_one!(f(12428269, -130; f32) => b"91308", -32);
- check_exact_one!(f(15334037, -146; f32) => b"171900", -36);
- check_exact_one!(f(11518287, -41; f32) => b"5237910", -5);
- check_exact_one!(f(12584953, -145; f32) => b"28216440", -36);
- check_exact_one!(f(15961084, -125; f32) => b"375243281", -30);
- check_exact_one!(f(14915817, -146; f32) => b"1672120916", -36);
- check_exact_one!(f(10845484, -102; f32) => b"21388945814", -23);
- check_exact_one!(f(16431059, -61; f32) => b"712583594561", -11);
-
- // [1], Table 17: Stress Inputs for Converting 24-bit Binary to Decimal, > 1/2 ULP
- check_exact_one!(f(16093626, 69; f32) => b"1", 29);
- check_exact_one!(f( 9983778, 25; f32) => b"34", 15);
- check_exact_one!(f(12745034, 104; f32) => b"259", 39);
- check_exact_one!(f(12706553, 72; f32) => b"6001", 29);
- check_exact_one!(f(11005028, 45; f32) => b"38721", 21);
- check_exact_one!(f(15059547, 71; f32) => b"355584", 29);
- check_exact_one!(f(16015691, -99; f32) => b"2526831", -22);
- check_exact_one!(f( 8667859, 56; f32) => b"62458507", 24);
- check_exact_one!(f(14855922, -82; f32) => b"307213267", -17);
- check_exact_one!(f(14855922, -83; f32) => b"1536066333", -17);
- check_exact_one!(f(10144164, -110; f32) => b"78147796834", -26);
- check_exact_one!(f(13248074, 95; f32) => b"524810279937", 36);
-}
-
-pub fn f64_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
- // 0.0999999999999999777955395074968691915273...
- // 0.1000000000000000055511151231257827021181...
- // 0.1000000000000000333066907387546962127089...
- check_shortest!(f(0.1f64) => b"1", 0);
-
- // this example is explicitly mentioned in the paper.
- // 10^3 * 0.0999999999999999857891452847979962825775...
- // 10^3 * 0.1 (exact)
- // 10^3 * 0.1000000000000000142108547152020037174224...
- check_shortest!(f(100.0f64) => b"1", 3);
-
- // 0.3333333333333332593184650249895639717578...
- // 0.3333333333333333148296162562473909929394... (1/3 in the default rounding)
- // 0.3333333333333333703407674875052180141210...
- check_shortest!(f(1.0f64/3.0) => b"3333333333333333", 0);
-
- // explicit test case for equally closest representations.
- // Dragon has its own tie-breaking rule; Grisu should fall back.
- // 10^1 * 0.1000007629394531027955395074968691915273...
- // 10^1 * 0.100000762939453125 (exact)
- // 10^1 * 0.1000007629394531472044604925031308084726...
- check_shortest!(f(1.00000762939453125f64) => b"10000076293945313", 1);
-
- // 10^1 * 0.3141591999999999718085064159822650253772...
- // 10^1 * 0.3141592000000000162174274009885266423225...
- // 10^1 * 0.3141592000000000606263483859947882592678...
- check_shortest!(f(3.141592f64) => b"3141592", 1);
-
- // 10^18 * 0.314159199999999936
- // 10^18 * 0.3141592 (exact)
- // 10^18 * 0.314159200000000064
- check_shortest!(f(3.141592e17f64) => b"3141592", 18);
-
- // regression test for decoders
- // 10^20 * 0.18446744073709549568
- // 10^20 * 0.18446744073709551616
- // 10^20 * 0.18446744073709555712
- check_shortest!(f(ldexp_f64(1.0, 64)) => b"18446744073709552", 20);
-
- // pathological case: high = 10^23 (exact). tie breaking should always prefer that.
- // 10^24 * 0.099999999999999974834176
- // 10^24 * 0.099999999999999991611392
- // 10^24 * 0.100000000000000008388608
- check_shortest!(f(1.0e23f64) => b"1", 24);
-
- // 10^309 * 0.1797693134862315508561243283845062402343...
- // 10^309 * 0.1797693134862315708145274237317043567980...
- // 10^309 * 0.1797693134862315907729305190789024733617...
- check_shortest!(f(f64::MAX) => b"17976931348623157", 309);
-
- // 10^-307 * 0.2225073858507200889024586876085859887650...
- // 10^-307 * 0.2225073858507201383090232717332404064219...
- // 10^-307 * 0.2225073858507201877155878558578948240788...
- check_shortest!(f(f64::MIN_POSITIVE) => b"22250738585072014", -307);
-
- // 10^-323 * 0
- // 10^-323 * 0.4940656458412465441765687928682213723650...
- // 10^-323 * 0.9881312916824930883531375857364427447301...
- let minf64 = ldexp_f64(1.0, -1074);
- check_shortest!(f(minf64) => b"5", -323);
-}
-
-pub fn f64_exact_sanity_test<F>(mut f: F)
- where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
- let minf64 = ldexp_f64(1.0, -1074);
-
- check_exact!(f(0.1f64) => b"1000000000000000055511151231257827021181", 0);
- check_exact!(f(0.45f64) => b"4500000000000000111022302462515654042363", 0);
- check_exact!(f(0.5f64) => b"5 ", 0);
- check_exact!(f(0.95f64) => b"9499999999999999555910790149937383830547", 0);
- check_exact!(f(100.0f64) => b"1 ", 3);
- check_exact!(f(999.5f64) => b"9995000000000000000000000000000000000000", 3);
- check_exact!(f(1.0f64/3.0) => b"3333333333333333148296162562473909929394", 0);
- check_exact!(f(3.141592f64) => b"3141592000000000162174274009885266423225", 1);
- check_exact!(f(3.141592e17f64) => b"3141592 ", 18);
- check_exact!(f(1.0e23f64) => b"99999999999999991611392 ", 23);
- check_exact!(f(f64::MAX) => b"1797693134862315708145274237317043567980", 309);
- check_exact!(f(f64::MIN_POSITIVE) => b"2225073858507201383090232717332404064219", -307);
- check_exact!(f(minf64) => b"4940656458412465441765687928682213723650\
- 5980261432476442558568250067550727020875\
- 1865299836361635992379796564695445717730\
- 9266567103559397963987747960107818781263\
- 0071319031140452784581716784898210368871\
- 8636056998730723050006387409153564984387\
- 3124733972731696151400317153853980741262\
- 3856559117102665855668676818703956031062\
- 4931945271591492455329305456544401127480\
- 1297099995419319894090804165633245247571\
- 4786901472678015935523861155013480352649\
- 3472019379026810710749170333222684475333\
- 5720832431936092382893458368060106011506\
- 1698097530783422773183292479049825247307\
- 7637592724787465608477820373446969953364\
- 7017972677717585125660551199131504891101\
- 4510378627381672509558373897335989936648\
- 0994116420570263709027924276754456522908\
- 7538682506419718265533447265625 ", -323);
-
- // [1], Table 3: Stress Inputs for Converting 53-bit Binary to Decimal, < 1/2 ULP
- check_exact_one!(f(8511030020275656, -342; f64) => b"9", -87);
- check_exact_one!(f(5201988407066741, -824; f64) => b"46", -232);
- check_exact_one!(f(6406892948269899, 237; f64) => b"141", 88);
- check_exact_one!(f(8431154198732492, 72; f64) => b"3981", 38);
- check_exact_one!(f(6475049196144587, 99; f64) => b"41040", 46);
- check_exact_one!(f(8274307542972842, 726; f64) => b"292084", 235);
- check_exact_one!(f(5381065484265332, -456; f64) => b"2891946", -121);
- check_exact_one!(f(6761728585499734, -1057; f64) => b"43787718", -302);
- check_exact_one!(f(7976538478610756, 376; f64) => b"122770163", 130);
- check_exact_one!(f(5982403858958067, 377; f64) => b"1841552452", 130);
- check_exact_one!(f(5536995190630837, 93; f64) => b"54835744350", 44);
- check_exact_one!(f(7225450889282194, 710; f64) => b"389190181146", 230);
- check_exact_one!(f(7225450889282194, 709; f64) => b"1945950905732", 230);
- check_exact_one!(f(8703372741147379, 117; f64) => b"14460958381605", 52);
- check_exact_one!(f(8944262675275217, -1001; f64) => b"417367747458531", -285);
- check_exact_one!(f(7459803696087692, -707; f64) => b"1107950772878888", -196);
- check_exact_one!(f(6080469016670379, -381; f64) => b"12345501366327440", -98);
- check_exact_one!(f(8385515147034757, 721; f64) => b"925031711960365024", 233);
- check_exact_one!(f(7514216811389786, -828; f64) => b"4198047150284889840", -233);
- check_exact_one!(f(8397297803260511, -345; f64) => b"11716315319786511046", -87);
- check_exact_one!(f(6733459239310543, 202; f64) => b"432810072844612493629", 77);
- check_exact_one!(f(8091450587292794, -473; f64) => b"3317710118160031081518", -126);
-
- // [1], Table 4: Stress Inputs for Converting 53-bit Binary to Decimal, > 1/2 ULP
- check_exact_one!(f(6567258882077402, 952; f64) => b"3", 303);
- check_exact_one!(f(6712731423444934, 535; f64) => b"76", 177);
- check_exact_one!(f(6712731423444934, 534; f64) => b"378", 177);
- check_exact_one!(f(5298405411573037, -957; f64) => b"4350", -272);
- check_exact_one!(f(5137311167659507, -144; f64) => b"23037", -27);
- check_exact_one!(f(6722280709661868, 363; f64) => b"126301", 126);
- check_exact_one!(f(5344436398034927, -169; f64) => b"7142211", -35);
- check_exact_one!(f(8369123604277281, -853; f64) => b"13934574", -240);
- check_exact_one!(f(8995822108487663, -780; f64) => b"141463449", -218);
- check_exact_one!(f(8942832835564782, -383; f64) => b"4539277920", -99);
- check_exact_one!(f(8942832835564782, -384; f64) => b"22696389598", -99);
- check_exact_one!(f(8942832835564782, -385; f64) => b"113481947988", -99);
- check_exact_one!(f(6965949469487146, -249; f64) => b"7700366561890", -59);
- check_exact_one!(f(6965949469487146, -250; f64) => b"38501832809448", -59);
- check_exact_one!(f(6965949469487146, -251; f64) => b"192509164047238", -59);
- check_exact_one!(f(7487252720986826, 548; f64) => b"6898586531774201", 181);
- check_exact_one!(f(5592117679628511, 164; f64) => b"13076622631878654", 66);
- check_exact_one!(f(8887055249355788, 665; f64) => b"136052020756121240", 217);
- check_exact_one!(f(6994187472632449, 690; f64) => b"3592810217475959676", 224);
- check_exact_one!(f(8797576579012143, 588; f64) => b"89125197712484551899", 193);
- check_exact_one!(f(7363326733505337, 272; f64) => b"558769757362301140950", 98);
- check_exact_one!(f(8549497411294502, -448; f64) => b"1176257830728540379990", -118);
-}
-
-pub fn more_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
- check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1,
- exp: 0, inclusive: true} => b"1", 18);
- check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1,
- exp: 0, inclusive: false} => b"99999999999999999", 17);
-}
-
-fn iterate<F, G, V>(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V) -> (usize, usize)
- where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
- G: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
- V: FnMut(usize) -> Decoded {
- assert!(k <= 1024);
-
- let mut npassed = 0; // f(x) = Some(g(x))
- let mut nignored = 0; // f(x) = None
-
- for i in 0..n {
- if (i & 0xfffff) == 0 {
- println!("in progress, {:x}/{:x} (ignored={} passed={} failed={})",
- i, n, nignored, npassed, i - nignored - npassed);
- }
-
- let decoded = v(i);
- let mut buf1 = [0; 1024];
- if let Some((len1, e1)) = f(&decoded, &mut buf1[..k]) {
- let mut buf2 = [0; 1024];
- let (len2, e2) = g(&decoded, &mut buf2[..k]);
- if e1 == e2 && &buf1[..len1] == &buf2[..len2] {
- npassed += 1;
- } else {
- println!("equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}",
- i, n, decoded, str::from_utf8(&buf1[..len1]).unwrap(), e1,
- str::from_utf8(&buf2[..len2]).unwrap(), e2);
- }
- } else {
- nignored += 1;
- }
- }
- println!("{}({}): done, ignored={} passed={} failed={}",
- func, k, nignored, npassed, n - nignored - npassed);
- assert!(nignored + npassed == n,
- "{}({}): {} out of {} values returns an incorrect value!",
- func, k, n - nignored - npassed, n);
- (npassed, nignored)
-}
-
-pub fn f32_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
- where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
- G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
- let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng());
- let f32_range = Range::new(0x0000_0001u32, 0x7f80_0000);
- iterate("f32_random_equivalence_test", k, n, f, g, |_| {
- let i: u32 = f32_range.ind_sample(&mut rng);
- let x: f32 = unsafe {mem::transmute(i)};
- decode_finite(x)
- });
-}
-
-pub fn f64_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
- where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
- G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
- let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng());
- let f64_range = Range::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000);
- iterate("f64_random_equivalence_test", k, n, f, g, |_| {
- let i: u64 = f64_range.ind_sample(&mut rng);
- let x: f64 = unsafe {mem::transmute(i)};
- decode_finite(x)
- });
-}
-
-pub fn f32_exhaustive_equivalence_test<F, G>(f: F, g: G, k: usize)
- where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
- G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
- // we have only 2^23 * (2^8 - 1) - 1 = 2,139,095,039 positive finite f32 values,
- // so why not simply testing all of them?
- //
- // this is of course very stressful (and thus should be behind an `#[ignore]` attribute),
- // but with `-C opt-level=3 -C lto` this only takes about an hour or so.
-
- // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e. all finite ranges
- let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test",
- k, 0x7f7f_ffff, f, g, |i: usize| {
- let x: f32 = unsafe {mem::transmute(i as u32 + 1)};
- decode_finite(x)
- });
- assert_eq!((npassed, nignored), (2121451881, 17643158));
-}
-
-fn to_string_with_parts<F>(mut f: F) -> String
- where F: for<'a> FnMut(&'a mut [u8], &'a mut [Part<'a>]) -> Formatted<'a> {
- let mut buf = [0; 1024];
- let mut parts = [Part::Zero(0); 16];
- let formatted = f(&mut buf, &mut parts);
- let mut ret = vec![0; formatted.len()];
- assert_eq!(formatted.write(&mut ret), Some(ret.len()));
- String::from_utf8(ret).unwrap()
-}
-
-pub fn to_shortest_str_test<F>(mut f_: F)
- where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
- use core::num::flt2dec::Sign::*;
-
- fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String
- where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
- to_string_with_parts(|buf, parts| to_shortest_str(|d,b| f(d,b), v, sign,
- frac_digits, upper, buf, parts))
- }
-
- let f = &mut f_;
-
- assert_eq!(to_string(f, 0.0, Minus, 0, false), "0");
- assert_eq!(to_string(f, 0.0, MinusRaw, 0, false), "0");
- assert_eq!(to_string(f, 0.0, MinusPlus, 0, false), "+0");
- assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0, false), "+0");
- assert_eq!(to_string(f, -0.0, Minus, 0, false), "0");
- assert_eq!(to_string(f, -0.0, MinusRaw, 0, false), "-0");
- assert_eq!(to_string(f, -0.0, MinusPlus, 0, false), "+0");
- assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0");
- assert_eq!(to_string(f, 0.0, Minus, 1, true), "0.0");
- assert_eq!(to_string(f, 0.0, MinusRaw, 1, true), "0.0");
- assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0.0");
- assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, true), "+0.0");
- assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.00000000");
- assert_eq!(to_string(f, -0.0, MinusRaw, 8, true), "-0.00000000");
- assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.00000000");
- assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, true), "-0.00000000");
-
- assert_eq!(to_string(f, 1.0/0.0, Minus, 0, false), "inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusRaw, 0, true), "inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusPlus, 0, false), "+inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, 0, true), "+inf");
- assert_eq!(to_string(f, 0.0/0.0, Minus, 0, false), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusRaw, 1, true), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusPlus, 8, false), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, 64, true), "NaN");
- assert_eq!(to_string(f, -1.0/0.0, Minus, 0, false), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusRaw, 1, true), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusPlus, 8, false), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64, true), "-inf");
-
- assert_eq!(to_string(f, 3.14, Minus, 0, false), "3.14");
- assert_eq!(to_string(f, 3.14, MinusRaw, 0, false), "3.14");
- assert_eq!(to_string(f, 3.14, MinusPlus, 0, false), "+3.14");
- assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0, false), "+3.14");
- assert_eq!(to_string(f, -3.14, Minus, 0, false), "-3.14");
- assert_eq!(to_string(f, -3.14, MinusRaw, 0, false), "-3.14");
- assert_eq!(to_string(f, -3.14, MinusPlus, 0, false), "-3.14");
- assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3.14");
- assert_eq!(to_string(f, 3.14, Minus, 1, true), "3.14");
- assert_eq!(to_string(f, 3.14, MinusRaw, 2, true), "3.14");
- assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.140");
- assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4, true), "+3.1400");
- assert_eq!(to_string(f, -3.14, Minus, 8, true), "-3.14000000");
- assert_eq!(to_string(f, -3.14, MinusRaw, 8, true), "-3.14000000");
- assert_eq!(to_string(f, -3.14, MinusPlus, 8, true), "-3.14000000");
- assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8, true), "-3.14000000");
-
- assert_eq!(to_string(f, 7.5e-11, Minus, 0, false), "0.000000000075");
- assert_eq!(to_string(f, 7.5e-11, Minus, 3, false), "0.000000000075");
- assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075");
- assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750");
-
- assert_eq!(to_string(f, 1.9971e20, Minus, 0, false), "199710000000000000000");
- assert_eq!(to_string(f, 1.9971e20, Minus, 1, false), "199710000000000000000.0");
- assert_eq!(to_string(f, 1.9971e20, Minus, 8, false), "199710000000000000000.00000000");
-
- assert_eq!(to_string(f, f32::MAX, Minus, 0, false), format!("34028235{:0>31}", ""));
- assert_eq!(to_string(f, f32::MAX, Minus, 1, false), format!("34028235{:0>31}.0", ""));
- assert_eq!(to_string(f, f32::MAX, Minus, 8, false), format!("34028235{:0>31}.00000000", ""));
-
- let minf32 = ldexp_f32(1.0, -149);
- assert_eq!(to_string(f, minf32, Minus, 0, false), format!("0.{:0>44}1", ""));
- assert_eq!(to_string(f, minf32, Minus, 45, false), format!("0.{:0>44}1", ""));
- assert_eq!(to_string(f, minf32, Minus, 46, false), format!("0.{:0>44}10", ""));
-
- assert_eq!(to_string(f, f64::MAX, Minus, 0, false),
- format!("17976931348623157{:0>292}", ""));
- assert_eq!(to_string(f, f64::MAX, Minus, 1, false),
- format!("17976931348623157{:0>292}.0", ""));
- assert_eq!(to_string(f, f64::MAX, Minus, 8, false),
- format!("17976931348623157{:0>292}.00000000", ""));
-
- let minf64 = ldexp_f64(1.0, -1074);
- assert_eq!(to_string(f, minf64, Minus, 0, false), format!("0.{:0>323}5", ""));
- assert_eq!(to_string(f, minf64, Minus, 324, false), format!("0.{:0>323}5", ""));
- assert_eq!(to_string(f, minf64, Minus, 325, false), format!("0.{:0>323}50", ""));
-
- // very large output
- assert_eq!(to_string(f, 1.1, Minus, 80000, false), format!("1.1{:0>79999}", ""));
-}
-
-pub fn to_shortest_exp_str_test<F>(mut f_: F)
- where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
- use core::num::flt2dec::Sign::*;
-
- fn to_string<T, F>(f: &mut F, v: T, sign: Sign, exp_bounds: (i16, i16), upper: bool) -> String
- where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
- to_string_with_parts(|buf, parts| to_shortest_exp_str(|d,b| f(d,b), v, sign,
- exp_bounds, upper, buf, parts))
- }
-
- let f = &mut f_;
-
- assert_eq!(to_string(f, 0.0, Minus, (-4, 16), false), "0");
- assert_eq!(to_string(f, 0.0, MinusRaw, (-4, 16), false), "0");
- assert_eq!(to_string(f, 0.0, MinusPlus, (-4, 16), false), "+0");
- assert_eq!(to_string(f, 0.0, MinusPlusRaw, (-4, 16), false), "+0");
- assert_eq!(to_string(f, -0.0, Minus, (-4, 16), false), "0");
- assert_eq!(to_string(f, -0.0, MinusRaw, (-4, 16), false), "-0");
- assert_eq!(to_string(f, -0.0, MinusPlus, (-4, 16), false), "+0");
- assert_eq!(to_string(f, -0.0, MinusPlusRaw, (-4, 16), false), "-0");
- assert_eq!(to_string(f, 0.0, Minus, ( 0, 0), true), "0E0");
- assert_eq!(to_string(f, 0.0, MinusRaw, ( 0, 0), false), "0e0");
- assert_eq!(to_string(f, 0.0, MinusPlus, (-9, -5), true), "+0E0");
- assert_eq!(to_string(f, 0.0, MinusPlusRaw, ( 5, 9), false), "+0e0");
- assert_eq!(to_string(f, -0.0, Minus, ( 0, 0), true), "0E0");
- assert_eq!(to_string(f, -0.0, MinusRaw, ( 0, 0), false), "-0e0");
- assert_eq!(to_string(f, -0.0, MinusPlus, (-9, -5), true), "+0E0");
- assert_eq!(to_string(f, -0.0, MinusPlusRaw, ( 5, 9), false), "-0e0");
-
- assert_eq!(to_string(f, 1.0/0.0, Minus, (-4, 16), false), "inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusRaw, (-4, 16), true), "inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusPlus, (-4, 16), false), "+inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, (-4, 16), true), "+inf");
- assert_eq!(to_string(f, 0.0/0.0, Minus, ( 0, 0), false), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusRaw, ( 0, 0), true), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusPlus, (-9, -5), false), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, ( 5, 9), true), "NaN");
- assert_eq!(to_string(f, -1.0/0.0, Minus, ( 0, 0), false), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusRaw, ( 0, 0), true), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusPlus, (-9, -5), false), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, ( 5, 9), true), "-inf");
-
- assert_eq!(to_string(f, 3.14, Minus, (-4, 16), false), "3.14");
- assert_eq!(to_string(f, 3.14, MinusRaw, (-4, 16), false), "3.14");
- assert_eq!(to_string(f, 3.14, MinusPlus, (-4, 16), false), "+3.14");
- assert_eq!(to_string(f, 3.14, MinusPlusRaw, (-4, 16), false), "+3.14");
- assert_eq!(to_string(f, -3.14, Minus, (-4, 16), false), "-3.14");
- assert_eq!(to_string(f, -3.14, MinusRaw, (-4, 16), false), "-3.14");
- assert_eq!(to_string(f, -3.14, MinusPlus, (-4, 16), false), "-3.14");
- assert_eq!(to_string(f, -3.14, MinusPlusRaw, (-4, 16), false), "-3.14");
- assert_eq!(to_string(f, 3.14, Minus, ( 0, 0), true), "3.14E0");
- assert_eq!(to_string(f, 3.14, MinusRaw, ( 0, 0), false), "3.14e0");
- assert_eq!(to_string(f, 3.14, MinusPlus, (-9, -5), true), "+3.14E0");
- assert_eq!(to_string(f, 3.14, MinusPlusRaw, ( 5, 9), false), "+3.14e0");
- assert_eq!(to_string(f, -3.14, Minus, ( 0, 0), true), "-3.14E0");
- assert_eq!(to_string(f, -3.14, MinusRaw, ( 0, 0), false), "-3.14e0");
- assert_eq!(to_string(f, -3.14, MinusPlus, (-9, -5), true), "-3.14E0");
- assert_eq!(to_string(f, -3.14, MinusPlusRaw, ( 5, 9), false), "-3.14e0");
-
- assert_eq!(to_string(f, 0.1, Minus, (-4, 16), false), "0.1");
- assert_eq!(to_string(f, 0.1, MinusRaw, (-4, 16), false), "0.1");
- assert_eq!(to_string(f, 0.1, MinusPlus, (-4, 16), false), "+0.1");
- assert_eq!(to_string(f, 0.1, MinusPlusRaw, (-4, 16), false), "+0.1");
- assert_eq!(to_string(f, -0.1, Minus, (-4, 16), false), "-0.1");
- assert_eq!(to_string(f, -0.1, MinusRaw, (-4, 16), false), "-0.1");
- assert_eq!(to_string(f, -0.1, MinusPlus, (-4, 16), false), "-0.1");
- assert_eq!(to_string(f, -0.1, MinusPlusRaw, (-4, 16), false), "-0.1");
- assert_eq!(to_string(f, 0.1, Minus, ( 0, 0), true), "1E-1");
- assert_eq!(to_string(f, 0.1, MinusRaw, ( 0, 0), false), "1e-1");
- assert_eq!(to_string(f, 0.1, MinusPlus, (-9, -5), true), "+1E-1");
- assert_eq!(to_string(f, 0.1, MinusPlusRaw, ( 5, 9), false), "+1e-1");
- assert_eq!(to_string(f, -0.1, Minus, ( 0, 0), true), "-1E-1");
- assert_eq!(to_string(f, -0.1, MinusRaw, ( 0, 0), false), "-1e-1");
- assert_eq!(to_string(f, -0.1, MinusPlus, (-9, -5), true), "-1E-1");
- assert_eq!(to_string(f, -0.1, MinusPlusRaw, ( 5, 9), false), "-1e-1");
-
- assert_eq!(to_string(f, 7.5e-11, Minus, ( -4, 16), false), "7.5e-11");
- assert_eq!(to_string(f, 7.5e-11, Minus, (-11, 10), false), "0.000000000075");
- assert_eq!(to_string(f, 7.5e-11, Minus, (-10, 11), false), "7.5e-11");
-
- assert_eq!(to_string(f, 1.9971e20, Minus, ( -4, 16), false), "1.9971e20");
- assert_eq!(to_string(f, 1.9971e20, Minus, (-20, 21), false), "199710000000000000000");
- assert_eq!(to_string(f, 1.9971e20, Minus, (-21, 20), false), "1.9971e20");
-
- // the true value of 1.0e23f64 is less than 10^23, but that shouldn't matter here
- assert_eq!(to_string(f, 1.0e23, Minus, (22, 23), false), "1e23");
- assert_eq!(to_string(f, 1.0e23, Minus, (23, 24), false), "100000000000000000000000");
- assert_eq!(to_string(f, 1.0e23, Minus, (24, 25), false), "1e23");
-
- assert_eq!(to_string(f, f32::MAX, Minus, ( -4, 16), false), "3.4028235e38");
- assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), "3.4028235e38");
- assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), format!("34028235{:0>31}", ""));
-
- let minf32 = ldexp_f32(1.0, -149);
- assert_eq!(to_string(f, minf32, Minus, ( -4, 16), false), "1e-45");
- assert_eq!(to_string(f, minf32, Minus, (-44, 45), false), "1e-45");
- assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), format!("0.{:0>44}1", ""));
-
- assert_eq!(to_string(f, f64::MAX, Minus, ( -4, 16), false),
- "1.7976931348623157e308");
- assert_eq!(to_string(f, f64::MAX, Minus, (-308, 309), false),
- format!("17976931348623157{:0>292}", ""));
- assert_eq!(to_string(f, f64::MAX, Minus, (-309, 308), false),
- "1.7976931348623157e308");
-
- let minf64 = ldexp_f64(1.0, -1074);
- assert_eq!(to_string(f, minf64, Minus, ( -4, 16), false), "5e-324");
- assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), format!("0.{:0>323}5", ""));
- assert_eq!(to_string(f, minf64, Minus, (-323, 324), false), "5e-324");
-
- assert_eq!(to_string(f, 1.1, Minus, (i16::MIN, i16::MAX), false), "1.1");
-}
-
-pub fn to_exact_exp_str_test<F>(mut f_: F)
- where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
- use core::num::flt2dec::Sign::*;
-
- fn to_string<T, F>(f: &mut F, v: T, sign: Sign, ndigits: usize, upper: bool) -> String
- where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
- to_string_with_parts(|buf, parts| to_exact_exp_str(|d,b,l| f(d,b,l), v, sign,
- ndigits, upper, buf, parts))
- }
-
- let f = &mut f_;
-
- assert_eq!(to_string(f, 0.0, Minus, 1, true), "0E0");
- assert_eq!(to_string(f, 0.0, MinusRaw, 1, false), "0e0");
- assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0E0");
- assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, false), "+0e0");
- assert_eq!(to_string(f, -0.0, Minus, 1, true), "0E0");
- assert_eq!(to_string(f, -0.0, MinusRaw, 1, false), "-0e0");
- assert_eq!(to_string(f, -0.0, MinusPlus, 1, true), "+0E0");
- assert_eq!(to_string(f, -0.0, MinusPlusRaw, 1, false), "-0e0");
- assert_eq!(to_string(f, 0.0, Minus, 2, true), "0.0E0");
- assert_eq!(to_string(f, 0.0, MinusRaw, 2, false), "0.0e0");
- assert_eq!(to_string(f, 0.0, MinusPlus, 2, true), "+0.0E0");
- assert_eq!(to_string(f, 0.0, MinusPlusRaw, 2, false), "+0.0e0");
- assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.0000000E0");
- assert_eq!(to_string(f, -0.0, MinusRaw, 8, false), "-0.0000000e0");
- assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.0000000E0");
- assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, false), "-0.0000000e0");
-
- assert_eq!(to_string(f, 1.0/0.0, Minus, 1, false), "inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusRaw, 1, true), "inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusPlus, 1, false), "+inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, 1, true), "+inf");
- assert_eq!(to_string(f, 0.0/0.0, Minus, 8, false), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusRaw, 8, true), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusPlus, 8, false), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, 8, true), "NaN");
- assert_eq!(to_string(f, -1.0/0.0, Minus, 64, false), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusRaw, 64, true), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusPlus, 64, false), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64, true), "-inf");
-
- assert_eq!(to_string(f, 3.14, Minus, 1, true), "3E0");
- assert_eq!(to_string(f, 3.14, MinusRaw, 1, false), "3e0");
- assert_eq!(to_string(f, 3.14, MinusPlus, 1, true), "+3E0");
- assert_eq!(to_string(f, 3.14, MinusPlusRaw, 1, false), "+3e0");
- assert_eq!(to_string(f, -3.14, Minus, 2, true), "-3.1E0");
- assert_eq!(to_string(f, -3.14, MinusRaw, 2, false), "-3.1e0");
- assert_eq!(to_string(f, -3.14, MinusPlus, 2, true), "-3.1E0");
- assert_eq!(to_string(f, -3.14, MinusPlusRaw, 2, false), "-3.1e0");
- assert_eq!(to_string(f, 3.14, Minus, 3, true), "3.14E0");
- assert_eq!(to_string(f, 3.14, MinusRaw, 3, false), "3.14e0");
- assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.14E0");
- assert_eq!(to_string(f, 3.14, MinusPlusRaw, 3, false), "+3.14e0");
- assert_eq!(to_string(f, -3.14, Minus, 4, true), "-3.140E0");
- assert_eq!(to_string(f, -3.14, MinusRaw, 4, false), "-3.140e0");
- assert_eq!(to_string(f, -3.14, MinusPlus, 4, true), "-3.140E0");
- assert_eq!(to_string(f, -3.14, MinusPlusRaw, 4, false), "-3.140e0");
-
- assert_eq!(to_string(f, 0.195, Minus, 1, false), "2e-1");
- assert_eq!(to_string(f, 0.195, MinusRaw, 1, true), "2E-1");
- assert_eq!(to_string(f, 0.195, MinusPlus, 1, false), "+2e-1");
- assert_eq!(to_string(f, 0.195, MinusPlusRaw, 1, true), "+2E-1");
- assert_eq!(to_string(f, -0.195, Minus, 2, false), "-2.0e-1");
- assert_eq!(to_string(f, -0.195, MinusRaw, 2, true), "-2.0E-1");
- assert_eq!(to_string(f, -0.195, MinusPlus, 2, false), "-2.0e-1");
- assert_eq!(to_string(f, -0.195, MinusPlusRaw, 2, true), "-2.0E-1");
- assert_eq!(to_string(f, 0.195, Minus, 3, false), "1.95e-1");
- assert_eq!(to_string(f, 0.195, MinusRaw, 3, true), "1.95E-1");
- assert_eq!(to_string(f, 0.195, MinusPlus, 3, false), "+1.95e-1");
- assert_eq!(to_string(f, 0.195, MinusPlusRaw, 3, true), "+1.95E-1");
- assert_eq!(to_string(f, -0.195, Minus, 4, false), "-1.950e-1");
- assert_eq!(to_string(f, -0.195, MinusRaw, 4, true), "-1.950E-1");
- assert_eq!(to_string(f, -0.195, MinusPlus, 4, false), "-1.950e-1");
- assert_eq!(to_string(f, -0.195, MinusPlusRaw, 4, true), "-1.950E-1");
-
- assert_eq!(to_string(f, 9.5, Minus, 1, false), "1e1");
- assert_eq!(to_string(f, 9.5, Minus, 2, false), "9.5e0");
- assert_eq!(to_string(f, 9.5, Minus, 3, false), "9.50e0");
- assert_eq!(to_string(f, 9.5, Minus, 30, false), "9.50000000000000000000000000000e0");
-
- assert_eq!(to_string(f, 1.0e25, Minus, 1, false), "1e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 2, false), "1.0e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 15, false), "1.00000000000000e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 16, false), "1.000000000000000e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 17, false), "1.0000000000000001e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 18, false), "1.00000000000000009e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 19, false), "1.000000000000000091e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 20, false), "1.0000000000000000906e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 21, false), "1.00000000000000009060e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 22, false), "1.000000000000000090597e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 23, false), "1.0000000000000000905970e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 24, false), "1.00000000000000009059697e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 25, false), "1.000000000000000090596966e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 26, false), "1.0000000000000000905969664e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 27, false), "1.00000000000000009059696640e25");
- assert_eq!(to_string(f, 1.0e25, Minus, 30, false), "1.00000000000000009059696640000e25");
-
- assert_eq!(to_string(f, 1.0e-6, Minus, 1, false), "1e-6");
- assert_eq!(to_string(f, 1.0e-6, Minus, 2, false), "1.0e-6");
- assert_eq!(to_string(f, 1.0e-6, Minus, 16, false), "1.000000000000000e-6");
- assert_eq!(to_string(f, 1.0e-6, Minus, 17, false), "9.9999999999999995e-7");
- assert_eq!(to_string(f, 1.0e-6, Minus, 18, false), "9.99999999999999955e-7");
- assert_eq!(to_string(f, 1.0e-6, Minus, 19, false), "9.999999999999999547e-7");
- assert_eq!(to_string(f, 1.0e-6, Minus, 20, false), "9.9999999999999995475e-7");
- assert_eq!(to_string(f, 1.0e-6, Minus, 30, false), "9.99999999999999954748111825886e-7");
- assert_eq!(to_string(f, 1.0e-6, Minus, 40, false),
- "9.999999999999999547481118258862586856139e-7");
- assert_eq!(to_string(f, 1.0e-6, Minus, 50, false),
- "9.9999999999999995474811182588625868561393872369081e-7");
- assert_eq!(to_string(f, 1.0e-6, Minus, 60, false),
- "9.99999999999999954748111825886258685613938723690807819366455e-7");
- assert_eq!(to_string(f, 1.0e-6, Minus, 70, false),
- "9.999999999999999547481118258862586856139387236908078193664550781250000e-7");
-
- assert_eq!(to_string(f, f32::MAX, Minus, 1, false), "3e38");
- assert_eq!(to_string(f, f32::MAX, Minus, 2, false), "3.4e38");
- assert_eq!(to_string(f, f32::MAX, Minus, 4, false), "3.403e38");
- assert_eq!(to_string(f, f32::MAX, Minus, 8, false), "3.4028235e38");
- assert_eq!(to_string(f, f32::MAX, Minus, 16, false), "3.402823466385289e38");
- assert_eq!(to_string(f, f32::MAX, Minus, 32, false), "3.4028234663852885981170418348452e38");
- assert_eq!(to_string(f, f32::MAX, Minus, 64, false),
- "3.402823466385288598117041834845169254400000000000000000000000000e38");
-
- let minf32 = ldexp_f32(1.0, -149);
- assert_eq!(to_string(f, minf32, Minus, 1, false), "1e-45");
- assert_eq!(to_string(f, minf32, Minus, 2, false), "1.4e-45");
- assert_eq!(to_string(f, minf32, Minus, 4, false), "1.401e-45");
- assert_eq!(to_string(f, minf32, Minus, 8, false), "1.4012985e-45");
- assert_eq!(to_string(f, minf32, Minus, 16, false), "1.401298464324817e-45");
- assert_eq!(to_string(f, minf32, Minus, 32, false), "1.4012984643248170709237295832899e-45");
- assert_eq!(to_string(f, minf32, Minus, 64, false),
- "1.401298464324817070923729583289916131280261941876515771757068284e-45");
- assert_eq!(to_string(f, minf32, Minus, 128, false),
- "1.401298464324817070923729583289916131280261941876515771757068283\
- 8897910826858606014866381883621215820312500000000000000000000000e-45");
-
- assert_eq!(to_string(f, f64::MAX, Minus, 1, false), "2e308");
- assert_eq!(to_string(f, f64::MAX, Minus, 2, false), "1.8e308");
- assert_eq!(to_string(f, f64::MAX, Minus, 4, false), "1.798e308");
- assert_eq!(to_string(f, f64::MAX, Minus, 8, false), "1.7976931e308");
- assert_eq!(to_string(f, f64::MAX, Minus, 16, false), "1.797693134862316e308");
- assert_eq!(to_string(f, f64::MAX, Minus, 32, false), "1.7976931348623157081452742373170e308");
- assert_eq!(to_string(f, f64::MAX, Minus, 64, false),
- "1.797693134862315708145274237317043567980705675258449965989174768e308");
- assert_eq!(to_string(f, f64::MAX, Minus, 128, false),
- "1.797693134862315708145274237317043567980705675258449965989174768\
- 0315726078002853876058955863276687817154045895351438246423432133e308");
- assert_eq!(to_string(f, f64::MAX, Minus, 256, false),
- "1.797693134862315708145274237317043567980705675258449965989174768\
- 0315726078002853876058955863276687817154045895351438246423432132\
- 6889464182768467546703537516986049910576551282076245490090389328\
- 9440758685084551339423045832369032229481658085593321233482747978e308");
- assert_eq!(to_string(f, f64::MAX, Minus, 512, false),
- "1.797693134862315708145274237317043567980705675258449965989174768\
- 0315726078002853876058955863276687817154045895351438246423432132\
- 6889464182768467546703537516986049910576551282076245490090389328\
- 9440758685084551339423045832369032229481658085593321233482747978\
- 2620414472316873817718091929988125040402618412485836800000000000\
- 0000000000000000000000000000000000000000000000000000000000000000\
- 0000000000000000000000000000000000000000000000000000000000000000\
- 0000000000000000000000000000000000000000000000000000000000000000e308");
-
- // okay, this is becoming tough. fortunately for us, this is almost the worst case.
- let minf64 = ldexp_f64(1.0, -1074);
- assert_eq!(to_string(f, minf64, Minus, 1, false), "5e-324");
- assert_eq!(to_string(f, minf64, Minus, 2, false), "4.9e-324");
- assert_eq!(to_string(f, minf64, Minus, 4, false), "4.941e-324");
- assert_eq!(to_string(f, minf64, Minus, 8, false), "4.9406565e-324");
- assert_eq!(to_string(f, minf64, Minus, 16, false), "4.940656458412465e-324");
- assert_eq!(to_string(f, minf64, Minus, 32, false), "4.9406564584124654417656879286822e-324");
- assert_eq!(to_string(f, minf64, Minus, 64, false),
- "4.940656458412465441765687928682213723650598026143247644255856825e-324");
- assert_eq!(to_string(f, minf64, Minus, 128, false),
- "4.940656458412465441765687928682213723650598026143247644255856825\
- 0067550727020875186529983636163599237979656469544571773092665671e-324");
- assert_eq!(to_string(f, minf64, Minus, 256, false),
- "4.940656458412465441765687928682213723650598026143247644255856825\
- 0067550727020875186529983636163599237979656469544571773092665671\
- 0355939796398774796010781878126300713190311404527845817167848982\
- 1036887186360569987307230500063874091535649843873124733972731696e-324");
- assert_eq!(to_string(f, minf64, Minus, 512, false),
- "4.940656458412465441765687928682213723650598026143247644255856825\
- 0067550727020875186529983636163599237979656469544571773092665671\
- 0355939796398774796010781878126300713190311404527845817167848982\
- 1036887186360569987307230500063874091535649843873124733972731696\
- 1514003171538539807412623856559117102665855668676818703956031062\
- 4931945271591492455329305456544401127480129709999541931989409080\
- 4165633245247571478690147267801593552386115501348035264934720193\
- 7902681071074917033322268447533357208324319360923828934583680601e-324");
- assert_eq!(to_string(f, minf64, Minus, 1024, false),
- "4.940656458412465441765687928682213723650598026143247644255856825\
- 0067550727020875186529983636163599237979656469544571773092665671\
- 0355939796398774796010781878126300713190311404527845817167848982\
- 1036887186360569987307230500063874091535649843873124733972731696\
- 1514003171538539807412623856559117102665855668676818703956031062\
- 4931945271591492455329305456544401127480129709999541931989409080\
- 4165633245247571478690147267801593552386115501348035264934720193\
- 7902681071074917033322268447533357208324319360923828934583680601\
- 0601150616980975307834227731832924790498252473077637592724787465\
- 6084778203734469699533647017972677717585125660551199131504891101\
- 4510378627381672509558373897335989936648099411642057026370902792\
- 4276754456522908753868250641971826553344726562500000000000000000\
- 0000000000000000000000000000000000000000000000000000000000000000\
- 0000000000000000000000000000000000000000000000000000000000000000\
- 0000000000000000000000000000000000000000000000000000000000000000\
- 0000000000000000000000000000000000000000000000000000000000000000e-324");
-
- // very large output
- assert_eq!(to_string(f, 0.0, Minus, 80000, false), format!("0.{:0>79999}e0", ""));
- assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), format!("1.{:0>79999}e1", ""));
- assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), format!("1.{:0>79999}e0", ""));
- assert_eq!(to_string(f, 1.0e-1, Minus, 80000, false),
- format!("1.000000000000000055511151231257827021181583404541015625{:0>79945}\
- e-1", ""));
- assert_eq!(to_string(f, 1.0e-20, Minus, 80000, false),
- format!("9.999999999999999451532714542095716517295037027873924471077157760\
- 66783064379706047475337982177734375{:0>79901}e-21", ""));
-}
-
-pub fn to_exact_fixed_str_test<F>(mut f_: F)
- where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
- use core::num::flt2dec::Sign::*;
-
- fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String
- where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
- to_string_with_parts(|buf, parts| to_exact_fixed_str(|d,b,l| f(d,b,l), v, sign,
- frac_digits, upper, buf, parts))
- }
-
- let f = &mut f_;
-
- assert_eq!(to_string(f, 0.0, Minus, 0, false), "0");
- assert_eq!(to_string(f, 0.0, MinusRaw, 0, false), "0");
- assert_eq!(to_string(f, 0.0, MinusPlus, 0, false), "+0");
- assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0, false), "+0");
- assert_eq!(to_string(f, -0.0, Minus, 0, false), "0");
- assert_eq!(to_string(f, -0.0, MinusRaw, 0, false), "-0");
- assert_eq!(to_string(f, -0.0, MinusPlus, 0, false), "+0");
- assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0");
- assert_eq!(to_string(f, 0.0, Minus, 1, true), "0.0");
- assert_eq!(to_string(f, 0.0, MinusRaw, 1, true), "0.0");
- assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0.0");
- assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, true), "+0.0");
- assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.00000000");
- assert_eq!(to_string(f, -0.0, MinusRaw, 8, true), "-0.00000000");
- assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.00000000");
- assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, true), "-0.00000000");
-
- assert_eq!(to_string(f, 1.0/0.0, Minus, 0, false), "inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusRaw, 1, true), "inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusPlus, 8, false), "+inf");
- assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, 64, true), "+inf");
- assert_eq!(to_string(f, 0.0/0.0, Minus, 0, false), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusRaw, 1, true), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusPlus, 8, false), "NaN");
- assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, 64, true), "NaN");
- assert_eq!(to_string(f, -1.0/0.0, Minus, 0, false), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusRaw, 1, true), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusPlus, 8, false), "-inf");
- assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64, true), "-inf");
-
- assert_eq!(to_string(f, 3.14, Minus, 0, false), "3");
- assert_eq!(to_string(f, 3.14, MinusRaw, 0, false), "3");
- assert_eq!(to_string(f, 3.14, MinusPlus, 0, false), "+3");
- assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0, false), "+3");
- assert_eq!(to_string(f, -3.14, Minus, 0, false), "-3");
- assert_eq!(to_string(f, -3.14, MinusRaw, 0, false), "-3");
- assert_eq!(to_string(f, -3.14, MinusPlus, 0, false), "-3");
- assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3");
- assert_eq!(to_string(f, 3.14, Minus, 1, true), "3.1");
- assert_eq!(to_string(f, 3.14, MinusRaw, 2, true), "3.14");
- assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.140");
- assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4, true), "+3.1400");
- assert_eq!(to_string(f, -3.14, Minus, 8, true), "-3.14000000");
- assert_eq!(to_string(f, -3.14, MinusRaw, 8, true), "-3.14000000");
- assert_eq!(to_string(f, -3.14, MinusPlus, 8, true), "-3.14000000");
- assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8, true), "-3.14000000");
-
- assert_eq!(to_string(f, 0.195, Minus, 0, false), "0");
- assert_eq!(to_string(f, 0.195, MinusRaw, 0, false), "0");
- assert_eq!(to_string(f, 0.195, MinusPlus, 0, false), "+0");
- assert_eq!(to_string(f, 0.195, MinusPlusRaw, 0, false), "+0");
- assert_eq!(to_string(f, -0.195, Minus, 0, false), "-0");
- assert_eq!(to_string(f, -0.195, MinusRaw, 0, false), "-0");
- assert_eq!(to_string(f, -0.195, MinusPlus, 0, false), "-0");
- assert_eq!(to_string(f, -0.195, MinusPlusRaw, 0, false), "-0");
- assert_eq!(to_string(f, 0.195, Minus, 1, true), "0.2");
- assert_eq!(to_string(f, 0.195, MinusRaw, 2, true), "0.20");
- assert_eq!(to_string(f, 0.195, MinusPlus, 3, true), "+0.195");
- assert_eq!(to_string(f, 0.195, MinusPlusRaw, 4, true), "+0.1950");
- assert_eq!(to_string(f, -0.195, Minus, 5, true), "-0.19500");
- assert_eq!(to_string(f, -0.195, MinusRaw, 6, true), "-0.195000");
- assert_eq!(to_string(f, -0.195, MinusPlus, 7, true), "-0.1950000");
- assert_eq!(to_string(f, -0.195, MinusPlusRaw, 8, true), "-0.19500000");
-
- assert_eq!(to_string(f, 999.5, Minus, 0, false), "1000");
- assert_eq!(to_string(f, 999.5, Minus, 1, false), "999.5");
- assert_eq!(to_string(f, 999.5, Minus, 2, false), "999.50");
- assert_eq!(to_string(f, 999.5, Minus, 3, false), "999.500");
- assert_eq!(to_string(f, 999.5, Minus, 30, false), "999.500000000000000000000000000000");
-
- assert_eq!(to_string(f, 0.5, Minus, 0, false), "1");
- assert_eq!(to_string(f, 0.5, Minus, 1, false), "0.5");
- assert_eq!(to_string(f, 0.5, Minus, 2, false), "0.50");
- assert_eq!(to_string(f, 0.5, Minus, 3, false), "0.500");
-
- assert_eq!(to_string(f, 0.95, Minus, 0, false), "1");
- assert_eq!(to_string(f, 0.95, Minus, 1, false), "0.9"); // because it really is less than 0.95
- assert_eq!(to_string(f, 0.95, Minus, 2, false), "0.95");
- assert_eq!(to_string(f, 0.95, Minus, 3, false), "0.950");
- assert_eq!(to_string(f, 0.95, Minus, 10, false), "0.9500000000");
- assert_eq!(to_string(f, 0.95, Minus, 30, false), "0.949999999999999955591079014994");
-
- assert_eq!(to_string(f, 0.095, Minus, 0, false), "0");
- assert_eq!(to_string(f, 0.095, Minus, 1, false), "0.1");
- assert_eq!(to_string(f, 0.095, Minus, 2, false), "0.10");
- assert_eq!(to_string(f, 0.095, Minus, 3, false), "0.095");
- assert_eq!(to_string(f, 0.095, Minus, 4, false), "0.0950");
- assert_eq!(to_string(f, 0.095, Minus, 10, false), "0.0950000000");
- assert_eq!(to_string(f, 0.095, Minus, 30, false), "0.095000000000000001110223024625");
-
- assert_eq!(to_string(f, 0.0095, Minus, 0, false), "0");
- assert_eq!(to_string(f, 0.0095, Minus, 1, false), "0.0");
- assert_eq!(to_string(f, 0.0095, Minus, 2, false), "0.01");
- assert_eq!(to_string(f, 0.0095, Minus, 3, false), "0.009"); // really is less than 0.0095
- assert_eq!(to_string(f, 0.0095, Minus, 4, false), "0.0095");
- assert_eq!(to_string(f, 0.0095, Minus, 5, false), "0.00950");
- assert_eq!(to_string(f, 0.0095, Minus, 10, false), "0.0095000000");
- assert_eq!(to_string(f, 0.0095, Minus, 30, false), "0.009499999999999999764077607267");
-
- assert_eq!(to_string(f, 7.5e-11, Minus, 0, false), "0");
- assert_eq!(to_string(f, 7.5e-11, Minus, 3, false), "0.000");
- assert_eq!(to_string(f, 7.5e-11, Minus, 10, false), "0.0000000001");
- assert_eq!(to_string(f, 7.5e-11, Minus, 11, false), "0.00000000007"); // ditto
- assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075");
- assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750");
- assert_eq!(to_string(f, 7.5e-11, Minus, 20, false), "0.00000000007500000000");
- assert_eq!(to_string(f, 7.5e-11, Minus, 30, false), "0.000000000074999999999999999501");
-
- assert_eq!(to_string(f, 1.0e25, Minus, 0, false), "10000000000000000905969664");
- assert_eq!(to_string(f, 1.0e25, Minus, 1, false), "10000000000000000905969664.0");
- assert_eq!(to_string(f, 1.0e25, Minus, 3, false), "10000000000000000905969664.000");
-
- assert_eq!(to_string(f, 1.0e-6, Minus, 0, false), "0");
- assert_eq!(to_string(f, 1.0e-6, Minus, 3, false), "0.000");
- assert_eq!(to_string(f, 1.0e-6, Minus, 6, false), "0.000001");
- assert_eq!(to_string(f, 1.0e-6, Minus, 9, false), "0.000001000");
- assert_eq!(to_string(f, 1.0e-6, Minus, 12, false), "0.000001000000");
- assert_eq!(to_string(f, 1.0e-6, Minus, 22, false), "0.0000010000000000000000");
- assert_eq!(to_string(f, 1.0e-6, Minus, 23, false), "0.00000099999999999999995");
- assert_eq!(to_string(f, 1.0e-6, Minus, 24, false), "0.000000999999999999999955");
- assert_eq!(to_string(f, 1.0e-6, Minus, 25, false), "0.0000009999999999999999547");
- assert_eq!(to_string(f, 1.0e-6, Minus, 35, false), "0.00000099999999999999995474811182589");
- assert_eq!(to_string(f, 1.0e-6, Minus, 45, false),
- "0.000000999999999999999954748111825886258685614");
- assert_eq!(to_string(f, 1.0e-6, Minus, 55, false),
- "0.0000009999999999999999547481118258862586856139387236908");
- assert_eq!(to_string(f, 1.0e-6, Minus, 65, false),
- "0.00000099999999999999995474811182588625868561393872369080781936646");
- assert_eq!(to_string(f, 1.0e-6, Minus, 75, false),
- "0.000000999999999999999954748111825886258685613938723690807819366455078125000");
-
- assert_eq!(to_string(f, f32::MAX, Minus, 0, false),
- "340282346638528859811704183484516925440");
- assert_eq!(to_string(f, f32::MAX, Minus, 1, false),
- "340282346638528859811704183484516925440.0");
- assert_eq!(to_string(f, f32::MAX, Minus, 2, false),
- "340282346638528859811704183484516925440.00");
-
- let minf32 = ldexp_f32(1.0, -149);
- assert_eq!(to_string(f, minf32, Minus, 0, false), "0");
- assert_eq!(to_string(f, minf32, Minus, 1, false), "0.0");
- assert_eq!(to_string(f, minf32, Minus, 2, false), "0.00");
- assert_eq!(to_string(f, minf32, Minus, 4, false), "0.0000");
- assert_eq!(to_string(f, minf32, Minus, 8, false), "0.00000000");
- assert_eq!(to_string(f, minf32, Minus, 16, false), "0.0000000000000000");
- assert_eq!(to_string(f, minf32, Minus, 32, false), "0.00000000000000000000000000000000");
- assert_eq!(to_string(f, minf32, Minus, 64, false),
- "0.0000000000000000000000000000000000000000000014012984643248170709");
- assert_eq!(to_string(f, minf32, Minus, 128, false),
- "0.0000000000000000000000000000000000000000000014012984643248170709\
- 2372958328991613128026194187651577175706828388979108268586060149");
- assert_eq!(to_string(f, minf32, Minus, 256, false),
- "0.0000000000000000000000000000000000000000000014012984643248170709\
- 2372958328991613128026194187651577175706828388979108268586060148\
- 6638188362121582031250000000000000000000000000000000000000000000\
- 0000000000000000000000000000000000000000000000000000000000000000");
-
- assert_eq!(to_string(f, f64::MAX, Minus, 0, false),
- "1797693134862315708145274237317043567980705675258449965989174768\
- 0315726078002853876058955863276687817154045895351438246423432132\
- 6889464182768467546703537516986049910576551282076245490090389328\
- 9440758685084551339423045832369032229481658085593321233482747978\
- 26204144723168738177180919299881250404026184124858368");
- assert_eq!(to_string(f, f64::MAX, Minus, 10, false),
- "1797693134862315708145274237317043567980705675258449965989174768\
- 0315726078002853876058955863276687817154045895351438246423432132\
- 6889464182768467546703537516986049910576551282076245490090389328\
- 9440758685084551339423045832369032229481658085593321233482747978\
- 26204144723168738177180919299881250404026184124858368.0000000000");
-
- let minf64 = ldexp_f64(1.0, -1074);
- assert_eq!(to_string(f, minf64, Minus, 0, false), "0");
- assert_eq!(to_string(f, minf64, Minus, 1, false), "0.0");
- assert_eq!(to_string(f, minf64, Minus, 10, false), "0.0000000000");
- assert_eq!(to_string(f, minf64, Minus, 100, false),
- "0.0000000000000000000000000000000000000000000000000000000000000000\
- 000000000000000000000000000000000000");
- assert_eq!(to_string(f, minf64, Minus, 1000, false),
- "0.0000000000000000000000000000000000000000000000000000000000000000\
- 0000000000000000000000000000000000000000000000000000000000000000\
- 0000000000000000000000000000000000000000000000000000000000000000\
- 0000000000000000000000000000000000000000000000000000000000000000\
- 0000000000000000000000000000000000000000000000000000000000000000\
- 0004940656458412465441765687928682213723650598026143247644255856\
- 8250067550727020875186529983636163599237979656469544571773092665\
- 6710355939796398774796010781878126300713190311404527845817167848\
- 9821036887186360569987307230500063874091535649843873124733972731\
- 6961514003171538539807412623856559117102665855668676818703956031\
- 0624931945271591492455329305456544401127480129709999541931989409\
- 0804165633245247571478690147267801593552386115501348035264934720\
- 1937902681071074917033322268447533357208324319360923828934583680\
- 6010601150616980975307834227731832924790498252473077637592724787\
- 4656084778203734469699533647017972677717585125660551199131504891\
- 1014510378627381672509558373897335989937");
-
- // very large output
- assert_eq!(to_string(f, 0.0, Minus, 80000, false), format!("0.{:0>80000}", ""));
- assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), format!("10.{:0>80000}", ""));
- assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), format!("1.{:0>80000}", ""));
- assert_eq!(to_string(f, 1.0e-1, Minus, 80000, false),
- format!("0.1000000000000000055511151231257827021181583404541015625{:0>79945}", ""));
- assert_eq!(to_string(f, 1.0e-20, Minus, 80000, false),
- format!("0.0000000000000000000099999999999999994515327145420957165172950370\
- 2787392447107715776066783064379706047475337982177734375{:0>79881}", ""));
-}
-
+++ /dev/null
-// Copyright 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.
-
-use std::prelude::v1::*;
-use super::super::*;
-use core::num::bignum::Big32x40 as Big;
-use core::num::flt2dec::strategy::dragon::*;
-
-#[test]
-fn test_mul_pow10() {
- let mut prevpow10 = Big::from_small(1);
- for i in 1..340 {
- let mut curpow10 = Big::from_small(1);
- mul_pow10(&mut curpow10, i);
- assert_eq!(curpow10, *prevpow10.clone().mul_small(10));
- prevpow10 = curpow10;
- }
-}
-
-#[test]
-fn shortest_sanity_test() {
- f64_shortest_sanity_test(format_shortest);
- f32_shortest_sanity_test(format_shortest);
- more_shortest_sanity_test(format_shortest);
-}
-
-#[test]
-fn exact_sanity_test() {
- // This test ends up running what I can only assume is some corner-ish case
- // of the `exp2` library function, defined in whatever C runtime we're
- // using. In VS 2013 this function apparently had a bug as this test fails
- // when linked, but with VS 2015 the bug appears fixed as the test runs just
- // fine.
- //
- // The bug seems to be a difference in return value of `exp2(-1057)`, where
- // in VS 2013 it returns a double with the bit pattern 0x2 and in VS 2015 it
- // returns 0x20000.
- //
- // For now just ignore this test entirely on MSVC as it's tested elsewhere
- // anyway and we're not super interested in testing each platform's exp2
- // implementation.
- if !cfg!(target_env = "msvc") {
- f64_exact_sanity_test(format_exact);
- }
- f32_exact_sanity_test(format_exact);
-}
-
-#[test]
-fn test_to_shortest_str() {
- to_shortest_str_test(format_shortest);
-}
-
-#[test]
-fn test_to_shortest_exp_str() {
- to_shortest_exp_str_test(format_shortest);
-}
-
-#[test]
-fn test_to_exact_exp_str() {
- to_exact_exp_str_test(format_exact);
-}
-
-#[test]
-fn test_to_exact_fixed_str() {
- to_exact_fixed_str_test(format_exact);
-}
-
+++ /dev/null
-// Copyright 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.
-
-use std::i16;
-use super::super::*;
-use core::num::flt2dec::strategy::grisu::*;
-
-#[test]
-fn test_cached_power() {
- assert_eq!(CACHED_POW10.first().unwrap().1, CACHED_POW10_FIRST_E);
- assert_eq!(CACHED_POW10.last().unwrap().1, CACHED_POW10_LAST_E);
-
- for e in -1137..961 { // full range for f64
- let low = ALPHA - e - 64;
- let high = GAMMA - e - 64;
- let (_k, cached) = cached_power(low, high);
- assert!(low <= cached.e && cached.e <= high,
- "cached_power({}, {}) = {:?} is incorrect", low, high, cached);
- }
-}
-
-#[test]
-fn test_max_pow10_no_more_than() {
- let mut prevtenk = 1;
- for k in 1..10 {
- let tenk = prevtenk * 10;
- assert_eq!(max_pow10_no_more_than(tenk - 1), (k - 1, prevtenk));
- assert_eq!(max_pow10_no_more_than(tenk), (k, tenk));
- prevtenk = tenk;
- }
-}
-
-
-#[test]
-fn shortest_sanity_test() {
- f64_shortest_sanity_test(format_shortest);
- f32_shortest_sanity_test(format_shortest);
- more_shortest_sanity_test(format_shortest);
-}
-
-#[test]
-fn shortest_random_equivalence_test() {
- use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
- f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000);
- f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000);
-}
-
-#[test] #[ignore] // it is too expensive
-fn shortest_f32_exhaustive_equivalence_test() {
- // it is hard to directly test the optimality of the output, but we can at least test if
- // two different algorithms agree to each other.
- //
- // this reports the progress and the number of f32 values returned `None`.
- // with `--nocapture` (and plenty of time and appropriate rustc flags), this should print:
- // `done, ignored=17643158 passed=2121451881 failed=0`.
-
- use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
- f32_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS);
-}
-
-#[test] #[ignore] // it is too expensive
-fn shortest_f64_hard_random_equivalence_test() {
- // this again probably has to use appropriate rustc flags.
-
- use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
- f64_random_equivalence_test(format_shortest_opt, fallback,
- MAX_SIG_DIGITS, 100_000_000);
-}
-
-#[test]
-fn exact_sanity_test() {
- // See comments in dragon.rs's exact_sanity_test for why this test is
- // ignored on MSVC
- if !cfg!(target_env = "msvc") {
- f64_exact_sanity_test(format_exact);
- }
- f32_exact_sanity_test(format_exact);
-}
-
-#[test]
-fn exact_f32_random_equivalence_test() {
- use core::num::flt2dec::strategy::dragon::format_exact as fallback;
- for k in 1..21 {
- f32_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN),
- |d, buf| fallback(d, buf, i16::MIN), k, 1_000);
- }
-}
-
-#[test]
-fn exact_f64_random_equivalence_test() {
- use core::num::flt2dec::strategy::dragon::format_exact as fallback;
- for k in 1..21 {
- f64_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN),
- |d, buf| fallback(d, buf, i16::MIN), k, 1_000);
- }
-}
-
-#[test]
-fn test_to_shortest_str() {
- to_shortest_str_test(format_shortest);
-}
-
-#[test]
-fn test_to_shortest_exp_str() {
- to_shortest_exp_str_test(format_shortest);
-}
-
-#[test]
-fn test_to_exact_exp_str() {
- to_exact_exp_str_test(format_exact);
-}
-
-#[test]
-fn test_to_exact_fixed_str() {
- to_exact_fixed_str_test(format_exact);
-}
-
+++ /dev/null
-// Copyright 2014 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.
-
-int_module!(i16, i16);
+++ /dev/null
-// Copyright 2014 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.
-
-int_module!(i32, i32);
+++ /dev/null
-// Copyright 2014 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.
-
-int_module!(i64, i64);
+++ /dev/null
-// Copyright 2014 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.
-
-int_module!(i8, i8);
+++ /dev/null
-// Copyright 2014 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.
-
-macro_rules! int_module { ($T:ident, $T_i:ident) => (
-#[cfg(test)]
-mod tests {
- use core::$T_i::*;
- use core::isize;
- use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr};
- use core::mem;
-
- use num;
-
- #[test]
- fn test_overflows() {
- assert!(MAX > 0);
- assert!(MIN <= 0);
- assert!(MIN + MAX + 1 == 0);
- }
-
- #[test]
- fn test_num() {
- num::test_num(10 as $T, 2 as $T);
- }
-
- #[test]
- pub fn test_abs() {
- assert!((1 as $T).abs() == 1 as $T);
- assert!((0 as $T).abs() == 0 as $T);
- assert!((-1 as $T).abs() == 1 as $T);
- }
-
- #[test]
- fn test_signum() {
- assert!((1 as $T).signum() == 1 as $T);
- assert!((0 as $T).signum() == 0 as $T);
- assert!((-0 as $T).signum() == 0 as $T);
- assert!((-1 as $T).signum() == -1 as $T);
- }
-
- #[test]
- fn test_is_positive() {
- assert!((1 as $T).is_positive());
- assert!(!(0 as $T).is_positive());
- assert!(!(-0 as $T).is_positive());
- assert!(!(-1 as $T).is_positive());
- }
-
- #[test]
- fn test_is_negative() {
- assert!(!(1 as $T).is_negative());
- assert!(!(0 as $T).is_negative());
- assert!(!(-0 as $T).is_negative());
- assert!((-1 as $T).is_negative());
- }
-
- #[test]
- fn test_bitwise_operators() {
- assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
- assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
- assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
- assert!(0b1110 as $T == (0b0111 as $T).shl(1));
- assert!(0b0111 as $T == (0b1110 as $T).shr(1));
- assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not());
- }
-
- const A: $T = 0b0101100;
- const B: $T = 0b0100001;
- const C: $T = 0b1111001;
-
- const _0: $T = 0;
- const _1: $T = !0;
-
- #[test]
- fn test_count_ones() {
- assert!(A.count_ones() == 3);
- assert!(B.count_ones() == 2);
- assert!(C.count_ones() == 5);
- }
-
- #[test]
- fn test_count_zeros() {
- let bits = mem::size_of::<$T>() * 8;
- assert!(A.count_zeros() == bits as u32 - 3);
- assert!(B.count_zeros() == bits as u32 - 2);
- assert!(C.count_zeros() == bits as u32 - 5);
- }
-
- #[test]
- fn test_rotate() {
- assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
- assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
- assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
-
- // Rotating these should make no difference
- //
- // We test using 124 bits because to ensure that overlong bit shifts do
- // not cause undefined behaviour. See #10183.
- assert_eq!(_0.rotate_left(124), _0);
- assert_eq!(_1.rotate_left(124), _1);
- assert_eq!(_0.rotate_right(124), _0);
- assert_eq!(_1.rotate_right(124), _1);
-
- // Rotating by 0 should have no effect
- assert_eq!(A.rotate_left(0), A);
- assert_eq!(B.rotate_left(0), B);
- assert_eq!(C.rotate_left(0), C);
- // Rotating by a multiple of word size should also have no effect
- assert_eq!(A.rotate_left(64), A);
- assert_eq!(B.rotate_left(64), B);
- assert_eq!(C.rotate_left(64), C);
- }
-
- #[test]
- fn test_swap_bytes() {
- assert_eq!(A.swap_bytes().swap_bytes(), A);
- assert_eq!(B.swap_bytes().swap_bytes(), B);
- assert_eq!(C.swap_bytes().swap_bytes(), C);
-
- // Swapping these should make no difference
- assert_eq!(_0.swap_bytes(), _0);
- assert_eq!(_1.swap_bytes(), _1);
- }
-
- #[test]
- fn test_le() {
- assert_eq!($T::from_le(A.to_le()), A);
- assert_eq!($T::from_le(B.to_le()), B);
- assert_eq!($T::from_le(C.to_le()), C);
- assert_eq!($T::from_le(_0), _0);
- assert_eq!($T::from_le(_1), _1);
- assert_eq!(_0.to_le(), _0);
- assert_eq!(_1.to_le(), _1);
- }
-
- #[test]
- fn test_be() {
- assert_eq!($T::from_be(A.to_be()), A);
- assert_eq!($T::from_be(B.to_be()), B);
- assert_eq!($T::from_be(C.to_be()), C);
- assert_eq!($T::from_be(_0), _0);
- assert_eq!($T::from_be(_1), _1);
- assert_eq!(_0.to_be(), _0);
- assert_eq!(_1.to_be(), _1);
- }
-
- #[test]
- fn test_signed_checked_div() {
- assert!((10 as $T).checked_div(2) == Some(5));
- assert!((5 as $T).checked_div(0) == None);
- assert!(isize::MIN.checked_div(-1) == None);
- }
-
- #[test]
- fn test_from_str() {
- fn from_str<T: ::std::str::FromStr>(t: &str) -> Option<T> {
- ::std::str::FromStr::from_str(t).ok()
- }
- assert_eq!(from_str::<$T>("0"), Some(0 as $T));
- assert_eq!(from_str::<$T>("3"), Some(3 as $T));
- assert_eq!(from_str::<$T>("10"), Some(10 as $T));
- assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32));
- assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
-
- assert_eq!(from_str::<$T>("-1"), Some(-1 as $T));
- assert_eq!(from_str::<$T>("-3"), Some(-3 as $T));
- assert_eq!(from_str::<$T>("-10"), Some(-10 as $T));
- assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
- assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));
-
- assert_eq!(from_str::<$T>(""), None);
- assert_eq!(from_str::<$T>(" "), None);
- assert_eq!(from_str::<$T>("x"), None);
- }
-
- #[test]
- fn test_from_str_radix() {
- assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
- assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
- assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
- assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32));
- assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
- assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
- assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
- assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T));
-
- assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T));
- assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
- assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T));
- assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
- assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
- assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
- assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T));
- assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T));
-
- assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
- assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
- }
-
- #[test]
- fn test_pow() {
- let mut r = 2 as $T;
-
- assert_eq!(r.pow(2), 4 as $T);
- assert_eq!(r.pow(0), 1 as $T);
- r = -2 as $T;
- assert_eq!(r.pow(2), 4 as $T);
- assert_eq!(r.pow(3), -8 as $T);
- }
-}
-
-)}
+++ /dev/null
-// Copyright 2014 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.
-
-use core::convert::TryFrom;
-use core::cmp::PartialEq;
-use core::fmt::Debug;
-use core::marker::Copy;
-use core::ops::{Add, Sub, Mul, Div, Rem};
-use core::option::Option;
-use core::option::Option::{Some, None};
-
-#[macro_use]
-mod int_macros;
-
-mod i8;
-mod i16;
-mod i32;
-mod i64;
-
-#[macro_use]
-mod uint_macros;
-
-mod u8;
-mod u16;
-mod u32;
-mod u64;
-
-mod flt2dec;
-mod dec2flt;
-mod bignum;
-
-/// Helper function for testing numeric operations
-pub fn test_num<T>(ten: T, two: T) where
- T: PartialEq
- + Add<Output=T> + Sub<Output=T>
- + Mul<Output=T> + Div<Output=T>
- + Rem<Output=T> + Debug
- + Copy
-{
- assert_eq!(ten.add(two), ten + two);
- assert_eq!(ten.sub(two), ten - two);
- assert_eq!(ten.mul(two), ten * two);
- assert_eq!(ten.div(two), ten / two);
- assert_eq!(ten.rem(two), ten % two);
-}
-
-#[test]
-fn from_str_issue7588() {
- let u : Option<u8> = u8::from_str_radix("1000", 10).ok();
- assert_eq!(u, None);
- let s : Option<i16> = i16::from_str_radix("80000", 10).ok();
- assert_eq!(s, None);
-}
-
-#[test]
-fn test_int_from_str_overflow() {
- let mut i8_val: i8 = 127;
- assert_eq!("127".parse::<i8>().ok(), Some(i8_val));
- assert_eq!("128".parse::<i8>().ok(), None);
-
- i8_val = i8_val.wrapping_add(1);
- assert_eq!("-128".parse::<i8>().ok(), Some(i8_val));
- assert_eq!("-129".parse::<i8>().ok(), None);
-
- let mut i16_val: i16 = 32_767;
- assert_eq!("32767".parse::<i16>().ok(), Some(i16_val));
- assert_eq!("32768".parse::<i16>().ok(), None);
-
- i16_val = i16_val.wrapping_add(1);
- assert_eq!("-32768".parse::<i16>().ok(), Some(i16_val));
- assert_eq!("-32769".parse::<i16>().ok(), None);
-
- let mut i32_val: i32 = 2_147_483_647;
- assert_eq!("2147483647".parse::<i32>().ok(), Some(i32_val));
- assert_eq!("2147483648".parse::<i32>().ok(), None);
-
- i32_val = i32_val.wrapping_add(1);
- assert_eq!("-2147483648".parse::<i32>().ok(), Some(i32_val));
- assert_eq!("-2147483649".parse::<i32>().ok(), None);
-
- let mut i64_val: i64 = 9_223_372_036_854_775_807;
- assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(i64_val));
- assert_eq!("9223372036854775808".parse::<i64>().ok(), None);
-
- i64_val = i64_val.wrapping_add(1);
- assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(i64_val));
- assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
-}
-
-#[test]
-fn test_leading_plus() {
- assert_eq!("+127".parse::<u8>().ok(), Some(127));
- assert_eq!("+9223372036854775807".parse::<i64>().ok(), Some(9223372036854775807));
-}
-
-#[test]
-fn test_invalid() {
- assert_eq!("--129".parse::<i8>().ok(), None);
- assert_eq!("++129".parse::<i8>().ok(), None);
- assert_eq!("Съешь".parse::<u8>().ok(), None);
-}
-
-#[test]
-fn test_empty() {
- assert_eq!("-".parse::<i8>().ok(), None);
- assert_eq!("+".parse::<i8>().ok(), None);
- assert_eq!("".parse::<u8>().ok(), None);
-}
-
-macro_rules! test_impl_from {
- ($fn_name: ident, $Small: ty, $Large: ty) => {
- #[test]
- fn $fn_name() {
- let small_max = <$Small>::max_value();
- let small_min = <$Small>::min_value();
- let large_max: $Large = small_max.into();
- let large_min: $Large = small_min.into();
- assert_eq!(large_max as $Small, small_max);
- assert_eq!(large_min as $Small, small_min);
- }
- }
-}
-
-// Unsigned -> Unsigned
-test_impl_from! { test_u8u16, u8, u16 }
-test_impl_from! { test_u8u32, u8, u32 }
-test_impl_from! { test_u8u64, u8, u64 }
-test_impl_from! { test_u8usize, u8, usize }
-test_impl_from! { test_u16u32, u16, u32 }
-test_impl_from! { test_u16u64, u16, u64 }
-test_impl_from! { test_u32u64, u32, u64 }
-
-// Signed -> Signed
-test_impl_from! { test_i8i16, i8, i16 }
-test_impl_from! { test_i8i32, i8, i32 }
-test_impl_from! { test_i8i64, i8, i64 }
-test_impl_from! { test_i8isize, i8, isize }
-test_impl_from! { test_i16i32, i16, i32 }
-test_impl_from! { test_i16i64, i16, i64 }
-test_impl_from! { test_i32i64, i32, i64 }
-
-// Unsigned -> Signed
-test_impl_from! { test_u8i16, u8, i16 }
-test_impl_from! { test_u8i32, u8, i32 }
-test_impl_from! { test_u8i64, u8, i64 }
-test_impl_from! { test_u16i32, u16, i32 }
-test_impl_from! { test_u16i64, u16, i64 }
-test_impl_from! { test_u32i64, u32, i64 }
-
-// Signed -> Float
-test_impl_from! { test_i8f32, i8, f32 }
-test_impl_from! { test_i8f64, i8, f64 }
-test_impl_from! { test_i16f32, i16, f32 }
-test_impl_from! { test_i16f64, i16, f64 }
-test_impl_from! { test_i32f64, i32, f64 }
-
-// Unsigned -> Float
-test_impl_from! { test_u8f32, u8, f32 }
-test_impl_from! { test_u8f64, u8, f64 }
-test_impl_from! { test_u16f32, u16, f32 }
-test_impl_from! { test_u16f64, u16, f64 }
-test_impl_from! { test_u32f64, u32, f64 }
-
-// Float -> Float
-#[test]
-fn test_f32f64() {
- use core::f32;
-
- let max: f64 = f32::MAX.into();
- assert_eq!(max as f32, f32::MAX);
- assert!(max.is_normal());
-
- let min: f64 = f32::MIN.into();
- assert_eq!(min as f32, f32::MIN);
- assert!(min.is_normal());
-
- let min_positive: f64 = f32::MIN_POSITIVE.into();
- assert_eq!(min_positive as f32, f32::MIN_POSITIVE);
- assert!(min_positive.is_normal());
-
- let epsilon: f64 = f32::EPSILON.into();
- assert_eq!(epsilon as f32, f32::EPSILON);
- assert!(epsilon.is_normal());
-
- let zero: f64 = (0.0f32).into();
- assert_eq!(zero as f32, 0.0f32);
- assert!(zero.is_sign_positive());
-
- let neg_zero: f64 = (-0.0f32).into();
- assert_eq!(neg_zero as f32, -0.0f32);
- assert!(neg_zero.is_sign_negative());
-
- let infinity: f64 = f32::INFINITY.into();
- assert_eq!(infinity as f32, f32::INFINITY);
- assert!(infinity.is_infinite());
- assert!(infinity.is_sign_positive());
-
- let neg_infinity: f64 = f32::NEG_INFINITY.into();
- assert_eq!(neg_infinity as f32, f32::NEG_INFINITY);
- assert!(neg_infinity.is_infinite());
- assert!(neg_infinity.is_sign_negative());
-
- let nan: f64 = f32::NAN.into();
- assert!(nan.is_nan());
-}
-
-macro_rules! test_impl_try_from_always_ok {
- ($fn_name:ident, $source:ty, $target: ty) => {
- #[test]
- fn $fn_name() {
- let max = <$source>::max_value();
- let min = <$source>::min_value();
- let zero: $source = 0;
- assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(),
- max as $target);
- assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(),
- min as $target);
- assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
- zero as $target);
- }
- }
-}
-
-test_impl_try_from_always_ok! { test_try_u8u8, u8, u8 }
-test_impl_try_from_always_ok! { test_try_u8u16, u8, u16 }
-test_impl_try_from_always_ok! { test_try_u8u32, u8, u32 }
-test_impl_try_from_always_ok! { test_try_u8u64, u8, u64 }
-test_impl_try_from_always_ok! { test_try_u8i16, u8, i16 }
-test_impl_try_from_always_ok! { test_try_u8i32, u8, i32 }
-test_impl_try_from_always_ok! { test_try_u8i64, u8, i64 }
-
-test_impl_try_from_always_ok! { test_try_u16u16, u16, u16 }
-test_impl_try_from_always_ok! { test_try_u16u32, u16, u32 }
-test_impl_try_from_always_ok! { test_try_u16u64, u16, u64 }
-test_impl_try_from_always_ok! { test_try_u16i32, u16, i32 }
-test_impl_try_from_always_ok! { test_try_u16i64, u16, i64 }
-
-test_impl_try_from_always_ok! { test_try_u32u32, u32, u32 }
-test_impl_try_from_always_ok! { test_try_u32u64, u32, u64 }
-test_impl_try_from_always_ok! { test_try_u32i64, u32, i64 }
-
-test_impl_try_from_always_ok! { test_try_u64u64, u64, u64 }
-
-test_impl_try_from_always_ok! { test_try_i8i8, i8, i8 }
-test_impl_try_from_always_ok! { test_try_i8i16, i8, i16 }
-test_impl_try_from_always_ok! { test_try_i8i32, i8, i32 }
-test_impl_try_from_always_ok! { test_try_i8i64, i8, i64 }
-
-test_impl_try_from_always_ok! { test_try_i16i16, i16, i16 }
-test_impl_try_from_always_ok! { test_try_i16i32, i16, i32 }
-test_impl_try_from_always_ok! { test_try_i16i64, i16, i64 }
-
-test_impl_try_from_always_ok! { test_try_i32i32, i32, i32 }
-test_impl_try_from_always_ok! { test_try_i32i64, i32, i64 }
-
-test_impl_try_from_always_ok! { test_try_i64i64, i64, i64 }
-
-macro_rules! test_impl_try_from_signed_to_unsigned_upper_ok {
- ($fn_name:ident, $source:ty, $target:ty) => {
- #[test]
- fn $fn_name() {
- let max = <$source>::max_value();
- let min = <$source>::min_value();
- let zero: $source = 0;
- let neg_one: $source = -1;
- assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(),
- max as $target);
- assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
- assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
- zero as $target);
- assert!(<$target as TryFrom<$source>>::try_from(neg_one).is_err());
- }
- }
-}
-
-test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u8, i8, u8 }
-test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u16, i8, u16 }
-test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u32, i8, u32 }
-test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u64, i8, u64 }
-
-test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u16, i16, u16 }
-test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u32, i16, u32 }
-test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u64, i16, u64 }
-
-test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u32, i32, u32 }
-test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u64, i32, u64 }
-
-test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i64u64, i64, u64 }
-
-macro_rules! test_impl_try_from_unsigned_to_signed_upper_err {
- ($fn_name:ident, $source:ty, $target:ty) => {
- #[test]
- fn $fn_name() {
- let max = <$source>::max_value();
- let min = <$source>::min_value();
- let zero: $source = 0;
- assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
- assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(),
- min as $target);
- assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
- zero as $target);
- }
- }
-}
-
-test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u8i8, u8, i8 }
-
-test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16i8, u16, i8 }
-test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16i16, u16, i16 }
-
-test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i8, u32, i8 }
-test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i16, u32, i16 }
-test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i32, u32, i32 }
-
-test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i8, u64, i8 }
-test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i16, u64, i16 }
-test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i32, u64, i32 }
-test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i64, u64, i64 }
-
-macro_rules! test_impl_try_from_same_sign_err {
- ($fn_name:ident, $source:ty, $target:ty) => {
- #[test]
- fn $fn_name() {
- let max = <$source>::max_value();
- let min = <$source>::min_value();
- let zero: $source = 0;
- let t_max = <$target>::max_value();
- let t_min = <$target>::min_value();
- assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
- if min != 0 {
- assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
- }
- assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
- zero as $target);
- assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source)
- .unwrap(),
- t_max as $target);
- assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source)
- .unwrap(),
- t_min as $target);
- }
- }
-}
-
-test_impl_try_from_same_sign_err! { test_try_u16u8, u16, u8 }
-
-test_impl_try_from_same_sign_err! { test_try_u32u8, u32, u8 }
-test_impl_try_from_same_sign_err! { test_try_u32u16, u32, u16 }
-
-test_impl_try_from_same_sign_err! { test_try_u64u8, u64, u8 }
-test_impl_try_from_same_sign_err! { test_try_u64u16, u64, u16 }
-test_impl_try_from_same_sign_err! { test_try_u64u32, u64, u32 }
-
-test_impl_try_from_same_sign_err! { test_try_i16i8, i16, i8 }
-
-test_impl_try_from_same_sign_err! { test_try_i32i8, i32, i8 }
-test_impl_try_from_same_sign_err! { test_try_i32i16, i32, i16 }
-
-test_impl_try_from_same_sign_err! { test_try_i64i8, i64, i8 }
-test_impl_try_from_same_sign_err! { test_try_i64i16, i64, i16 }
-test_impl_try_from_same_sign_err! { test_try_i64i32, i64, i32 }
-
-macro_rules! test_impl_try_from_signed_to_unsigned_err {
- ($fn_name:ident, $source:ty, $target:ty) => {
- #[test]
- fn $fn_name() {
- let max = <$source>::max_value();
- let min = <$source>::min_value();
- let zero: $source = 0;
- let t_max = <$target>::max_value();
- let t_min = <$target>::min_value();
- assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
- assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
- assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
- zero as $target);
- assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source)
- .unwrap(),
- t_max as $target);
- assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source)
- .unwrap(),
- t_min as $target);
- }
- }
-}
-
-test_impl_try_from_signed_to_unsigned_err! { test_try_i16u8, i16, u8 }
-
-test_impl_try_from_signed_to_unsigned_err! { test_try_i32u8, i32, u8 }
-test_impl_try_from_signed_to_unsigned_err! { test_try_i32u16, i32, u16 }
-
-test_impl_try_from_signed_to_unsigned_err! { test_try_i64u8, i64, u8 }
-test_impl_try_from_signed_to_unsigned_err! { test_try_i64u16, i64, u16 }
-test_impl_try_from_signed_to_unsigned_err! { test_try_i64u32, i64, u32 }
+++ /dev/null
-// Copyright 2014 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.
-
-uint_module!(u16, u16);
+++ /dev/null
-// Copyright 2014 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.
-
-uint_module!(u32, u32);
+++ /dev/null
-// Copyright 2014 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.
-
-uint_module!(u64, u64);
+++ /dev/null
-// Copyright 2014 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.
-
-uint_module!(u8, u8);
+++ /dev/null
-// Copyright 2014 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.
-
-macro_rules! uint_module { ($T:ident, $T_i:ident) => (
-#[cfg(test)]
-mod tests {
- use core::$T_i::*;
- use num;
- use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not};
- use std::str::FromStr;
- use std::mem;
-
- #[test]
- fn test_overflows() {
- assert!(MAX > 0);
- assert!(MIN <= 0);
- assert!((MIN + MAX).wrapping_add(1) == 0);
- }
-
- #[test]
- fn test_num() {
- num::test_num(10 as $T, 2 as $T);
- }
-
- #[test]
- fn test_bitwise_operators() {
- assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
- assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
- assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
- assert!(0b1110 as $T == (0b0111 as $T).shl(1));
- assert!(0b0111 as $T == (0b1110 as $T).shr(1));
- assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not());
- }
-
- const A: $T = 0b0101100;
- const B: $T = 0b0100001;
- const C: $T = 0b1111001;
-
- const _0: $T = 0;
- const _1: $T = !0;
-
- #[test]
- fn test_count_ones() {
- assert!(A.count_ones() == 3);
- assert!(B.count_ones() == 2);
- assert!(C.count_ones() == 5);
- }
-
- #[test]
- fn test_count_zeros() {
- let bits = mem::size_of::<$T>() * 8;
- assert!(A.count_zeros() == bits as u32 - 3);
- assert!(B.count_zeros() == bits as u32 - 2);
- assert!(C.count_zeros() == bits as u32 - 5);
- }
-
- #[test]
- fn test_rotate() {
- assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
- assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
- assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
-
- // Rotating these should make no difference
- //
- // We test using 124 bits because to ensure that overlong bit shifts do
- // not cause undefined behaviour. See #10183.
- assert_eq!(_0.rotate_left(124), _0);
- assert_eq!(_1.rotate_left(124), _1);
- assert_eq!(_0.rotate_right(124), _0);
- assert_eq!(_1.rotate_right(124), _1);
-
- // Rotating by 0 should have no effect
- assert_eq!(A.rotate_left(0), A);
- assert_eq!(B.rotate_left(0), B);
- assert_eq!(C.rotate_left(0), C);
- // Rotating by a multiple of word size should also have no effect
- assert_eq!(A.rotate_left(64), A);
- assert_eq!(B.rotate_left(64), B);
- assert_eq!(C.rotate_left(64), C);
- }
-
- #[test]
- fn test_swap_bytes() {
- assert_eq!(A.swap_bytes().swap_bytes(), A);
- assert_eq!(B.swap_bytes().swap_bytes(), B);
- assert_eq!(C.swap_bytes().swap_bytes(), C);
-
- // Swapping these should make no difference
- assert_eq!(_0.swap_bytes(), _0);
- assert_eq!(_1.swap_bytes(), _1);
- }
-
- #[test]
- fn test_le() {
- assert_eq!($T::from_le(A.to_le()), A);
- assert_eq!($T::from_le(B.to_le()), B);
- assert_eq!($T::from_le(C.to_le()), C);
- assert_eq!($T::from_le(_0), _0);
- assert_eq!($T::from_le(_1), _1);
- assert_eq!(_0.to_le(), _0);
- assert_eq!(_1.to_le(), _1);
- }
-
- #[test]
- fn test_be() {
- assert_eq!($T::from_be(A.to_be()), A);
- assert_eq!($T::from_be(B.to_be()), B);
- assert_eq!($T::from_be(C.to_be()), C);
- assert_eq!($T::from_be(_0), _0);
- assert_eq!($T::from_be(_1), _1);
- assert_eq!(_0.to_be(), _0);
- assert_eq!(_1.to_be(), _1);
- }
-
- #[test]
- fn test_unsigned_checked_div() {
- assert!((10 as $T).checked_div(2) == Some(5));
- assert!((5 as $T).checked_div(0) == None);
- }
-
- fn from_str<T: FromStr>(t: &str) -> Option<T> {
- FromStr::from_str(t).ok()
- }
-
- #[test]
- pub fn test_from_str() {
- assert_eq!(from_str::<$T>("0"), Some(0 as $T));
- assert_eq!(from_str::<$T>("3"), Some(3 as $T));
- assert_eq!(from_str::<$T>("10"), Some(10 as $T));
- assert_eq!(from_str::<u32>("123456789"), Some(123456789 as u32));
- assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
-
- assert_eq!(from_str::<$T>(""), None);
- assert_eq!(from_str::<$T>(" "), None);
- assert_eq!(from_str::<$T>("x"), None);
- }
-
- #[test]
- pub fn test_parse_bytes() {
- assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
- assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
- assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
- assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16));
- assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16));
- assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
-
- assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>);
- assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>);
- }
-}
-)}
+++ /dev/null
-// Copyright 2014 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.
-
-use core::ops::{Range, RangeFull, RangeFrom, RangeTo};
-
-// Test the Range structs without the syntactic sugar.
-
-#[test]
-fn test_range() {
- let r = Range { start: 2, end: 10 };
- let mut count = 0;
- for (i, ri) in r.enumerate() {
- assert!(ri == i + 2);
- assert!(ri >= 2 && ri < 10);
- count += 1;
- }
- assert!(count == 8);
-}
-
-#[test]
-fn test_range_from() {
- let r = RangeFrom { start: 2 };
- let mut count = 0;
- for (i, ri) in r.take(10).enumerate() {
- assert!(ri == i + 2);
- assert!(ri >= 2 && ri < 12);
- count += 1;
- }
- assert!(count == 10);
-}
-
-#[test]
-fn test_range_to() {
- // Not much to test.
- let _ = RangeTo { end: 42 };
-}
-
-#[test]
-fn test_full_range() {
- // Not much to test.
- let _ = RangeFull;
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use core::option::*;
-use core::mem;
-use core::clone::Clone;
-
-#[test]
-fn test_get_ptr() {
- unsafe {
- let x: Box<_> = box 0;
- let addr_x: *const isize = mem::transmute(&*x);
- let opt = Some(x);
- let y = opt.unwrap();
- let addr_y: *const isize = mem::transmute(&*y);
- assert_eq!(addr_x, addr_y);
- }
-}
-
-#[test]
-fn test_get_str() {
- let x = "test".to_string();
- let addr_x = x.as_ptr();
- let opt = Some(x);
- let y = opt.unwrap();
- let addr_y = y.as_ptr();
- assert_eq!(addr_x, addr_y);
-}
-
-#[test]
-fn test_get_resource() {
- use std::rc::Rc;
- use core::cell::RefCell;
-
- struct R {
- i: Rc<RefCell<isize>>,
- }
-
- impl Drop for R {
- fn drop(&mut self) {
- let ii = &*self.i;
- let i = *ii.borrow();
- *ii.borrow_mut() = i + 1;
- }
- }
-
- fn r(i: Rc<RefCell<isize>>) -> R {
- R {
- i: i
- }
- }
-
- let i = Rc::new(RefCell::new(0));
- {
- let x = r(i.clone());
- let opt = Some(x);
- let _y = opt.unwrap();
- }
- assert_eq!(*i.borrow(), 1);
-}
-
-#[test]
-fn test_option_dance() {
- let x = Some(());
- let mut y = Some(5);
- let mut y2 = 0;
- for _x in x {
- y2 = y.take().unwrap();
- }
- assert_eq!(y2, 5);
- assert!(y.is_none());
-}
-
-#[test] #[should_panic]
-fn test_option_too_much_dance() {
- struct A;
- let mut y = Some(A);
- let _y2 = y.take().unwrap();
- let _y3 = y.take().unwrap();
-}
-
-#[test]
-fn test_and() {
- let x: Option<isize> = Some(1);
- assert_eq!(x.and(Some(2)), Some(2));
- assert_eq!(x.and(None::<isize>), None);
-
- let x: Option<isize> = None;
- assert_eq!(x.and(Some(2)), None);
- assert_eq!(x.and(None::<isize>), None);
-}
-
-#[test]
-fn test_and_then() {
- let x: Option<isize> = Some(1);
- assert_eq!(x.and_then(|x| Some(x + 1)), Some(2));
- assert_eq!(x.and_then(|_| None::<isize>), None);
-
- let x: Option<isize> = None;
- assert_eq!(x.and_then(|x| Some(x + 1)), None);
- assert_eq!(x.and_then(|_| None::<isize>), None);
-}
-
-#[test]
-fn test_or() {
- let x: Option<isize> = Some(1);
- assert_eq!(x.or(Some(2)), Some(1));
- assert_eq!(x.or(None), Some(1));
-
- let x: Option<isize> = None;
- assert_eq!(x.or(Some(2)), Some(2));
- assert_eq!(x.or(None), None);
-}
-
-#[test]
-fn test_or_else() {
- let x: Option<isize> = Some(1);
- assert_eq!(x.or_else(|| Some(2)), Some(1));
- assert_eq!(x.or_else(|| None), Some(1));
-
- let x: Option<isize> = None;
- assert_eq!(x.or_else(|| Some(2)), Some(2));
- assert_eq!(x.or_else(|| None), None);
-}
-
-#[test]
-fn test_unwrap() {
- assert_eq!(Some(1).unwrap(), 1);
- let s = Some("hello".to_string()).unwrap();
- assert_eq!(s, "hello");
-}
-
-#[test]
-#[should_panic]
-fn test_unwrap_panic1() {
- let x: Option<isize> = None;
- x.unwrap();
-}
-
-#[test]
-#[should_panic]
-fn test_unwrap_panic2() {
- let x: Option<String> = None;
- x.unwrap();
-}
-
-#[test]
-fn test_unwrap_or() {
- let x: Option<isize> = Some(1);
- assert_eq!(x.unwrap_or(2), 1);
-
- let x: Option<isize> = None;
- assert_eq!(x.unwrap_or(2), 2);
-}
-
-#[test]
-fn test_unwrap_or_else() {
- let x: Option<isize> = Some(1);
- assert_eq!(x.unwrap_or_else(|| 2), 1);
-
- let x: Option<isize> = None;
- assert_eq!(x.unwrap_or_else(|| 2), 2);
-}
-
-#[test]
-fn test_iter() {
- let val = 5;
-
- let x = Some(val);
- let mut it = x.iter();
-
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(it.next(), Some(&val));
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert!(it.next().is_none());
-
- let mut it = (&x).into_iter();
- assert_eq!(it.next(), Some(&val));
-}
-
-#[test]
-fn test_mut_iter() {
- let mut val = 5;
- let new_val = 11;
-
- let mut x = Some(val);
- {
- let mut it = x.iter_mut();
-
- assert_eq!(it.size_hint(), (1, Some(1)));
-
- match it.next() {
- Some(interior) => {
- assert_eq!(*interior, val);
- *interior = new_val;
- }
- None => assert!(false),
- }
-
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert!(it.next().is_none());
- }
- assert_eq!(x, Some(new_val));
-
- let mut y = Some(val);
- let mut it = (&mut y).into_iter();
- assert_eq!(it.next(), Some(&mut val));
-}
-
-#[test]
-fn test_ord() {
- let small = Some(1.0f64);
- let big = Some(5.0f64);
- let nan = Some(0.0f64/0.0);
- assert!(!(nan < big));
- assert!(!(nan > big));
- assert!(small < big);
- assert!(None < big);
- assert!(big > None);
-}
-
-#[test]
-fn test_collect() {
- let v: Option<Vec<isize>> = (0..0).map(|_| Some(0)).collect();
- assert!(v == Some(vec![]));
-
- let v: Option<Vec<isize>> = (0..3).map(|x| Some(x)).collect();
- assert!(v == Some(vec![0, 1, 2]));
-
- let v: Option<Vec<isize>> = (0..3).map(|x| {
- if x > 1 { None } else { Some(x) }
- }).collect();
- assert!(v == None);
-
- // test that it does not take more elements than it needs
- let mut functions: [Box<Fn() -> Option<()>>; 3] =
- [box || Some(()), box || None, box || panic!()];
-
- let v: Option<Vec<()>> = functions.iter_mut().map(|f| (*f)()).collect();
-
- assert!(v == None);
-}
-
-
-#[test]
-fn test_cloned() {
- let val = 1;
- let val_ref = &val;
- let opt_none: Option<&'static u32> = None;
- let opt_ref = Some(&val);
- let opt_ref_ref = Some(&val_ref);
-
- // None works
- assert_eq!(opt_none.clone(), None);
- assert_eq!(opt_none.cloned(), None);
-
- // Immutable ref works
- assert_eq!(opt_ref.clone(), Some(&val));
- assert_eq!(opt_ref.cloned(), Some(1));
-
- // Double Immutable ref works
- assert_eq!(opt_ref_ref.clone(), Some(&val_ref));
- assert_eq!(opt_ref_ref.clone().cloned(), Some(&val));
- assert_eq!(opt_ref_ref.cloned().cloned(), Some(1));
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use core::ptr::*;
-use core::cell::RefCell;
-
-#[test]
-fn test() {
- unsafe {
- struct Pair {
- fst: isize,
- snd: isize
- };
- let mut p = Pair {fst: 10, snd: 20};
- let pptr: *mut Pair = &mut p;
- let iptr: *mut isize = pptr as *mut isize;
- assert_eq!(*iptr, 10);
- *iptr = 30;
- assert_eq!(*iptr, 30);
- assert_eq!(p.fst, 30);
-
- *pptr = Pair {fst: 50, snd: 60};
- assert_eq!(*iptr, 50);
- assert_eq!(p.fst, 50);
- assert_eq!(p.snd, 60);
-
- let v0 = vec![32000u16, 32001u16, 32002u16];
- let mut v1 = vec![0u16, 0u16, 0u16];
-
- copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
- assert!((v1[0] == 0u16 &&
- v1[1] == 32001u16 &&
- v1[2] == 0u16));
- copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
- assert!((v1[0] == 32002u16 &&
- v1[1] == 32001u16 &&
- v1[2] == 0u16));
- copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
- assert!((v1[0] == 32002u16 &&
- v1[1] == 32001u16 &&
- v1[2] == 32000u16));
- }
-}
-
-#[test]
-fn test_is_null() {
- let p: *const isize = null();
- assert!(p.is_null());
-
- let q = unsafe { p.offset(1) };
- assert!(!q.is_null());
-
- let mp: *mut isize = null_mut();
- assert!(mp.is_null());
-
- let mq = unsafe { mp.offset(1) };
- assert!(!mq.is_null());
-}
-
-#[test]
-fn test_as_ref() {
- unsafe {
- let p: *const isize = null();
- assert_eq!(p.as_ref(), None);
-
- let q: *const isize = &2;
- assert_eq!(q.as_ref().unwrap(), &2);
-
- let p: *mut isize = null_mut();
- assert_eq!(p.as_ref(), None);
-
- let q: *mut isize = &mut 2;
- assert_eq!(q.as_ref().unwrap(), &2);
-
- // Lifetime inference
- let u = 2isize;
- {
- let p = &u as *const isize;
- assert_eq!(p.as_ref().unwrap(), &2);
- }
- }
-}
-
-#[test]
-fn test_as_mut() {
- unsafe {
- let p: *mut isize = null_mut();
- assert!(p.as_mut() == None);
-
- let q: *mut isize = &mut 2;
- assert!(q.as_mut().unwrap() == &mut 2);
-
- // Lifetime inference
- let mut u = 2isize;
- {
- let p = &mut u as *mut isize;
- assert!(p.as_mut().unwrap() == &mut 2);
- }
- }
-}
-
-#[test]
-fn test_ptr_addition() {
- unsafe {
- let xs = vec![5; 16];
- let mut ptr = xs.as_ptr();
- let end = ptr.offset(16);
-
- while ptr < end {
- assert_eq!(*ptr, 5);
- ptr = ptr.offset(1);
- }
-
- let mut xs_mut = xs;
- let mut m_ptr = xs_mut.as_mut_ptr();
- let m_end = m_ptr.offset(16);
-
- while m_ptr < m_end {
- *m_ptr += 5;
- m_ptr = m_ptr.offset(1);
- }
-
- assert!(xs_mut == vec![10; 16]);
- }
-}
-
-#[test]
-fn test_ptr_subtraction() {
- unsafe {
- let xs = vec![0,1,2,3,4,5,6,7,8,9];
- let mut idx = 9;
- let ptr = xs.as_ptr();
-
- while idx >= 0 {
- assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
- idx = idx - 1;
- }
-
- let mut xs_mut = xs;
- let m_start = xs_mut.as_mut_ptr();
- let mut m_ptr = m_start.offset(9);
-
- while m_ptr >= m_start {
- *m_ptr += *m_ptr;
- m_ptr = m_ptr.offset(-1);
- }
-
- assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
- }
-}
-
-#[test]
-fn test_set_memory() {
- let mut xs = [0u8; 20];
- let ptr = xs.as_mut_ptr();
- unsafe { write_bytes(ptr, 5u8, xs.len()); }
- assert!(xs == [5u8; 20]);
-}
-
-#[test]
-fn test_unsized_unique() {
- let xs: &mut [i32] = &mut [1, 2, 3];
- let ptr = unsafe { Unique::new(xs as *mut [i32]) };
- let ys = unsafe { &mut **ptr };
- let zs: &mut [i32] = &mut [1, 2, 3];
- assert!(ys == zs);
-}
-
-#[test]
-#[allow(warnings)]
-// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
-// ABI, or even point to an actual executable code, because the function itself is never invoked.
-#[no_mangle]
-pub fn test_variadic_fnptr() {
- use core::hash::{Hash, SipHasher};
- extern {
- fn test_variadic_fnptr(_: u64, ...) -> f64;
- }
- let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
- let q = p.clone();
- assert_eq!(p, q);
- assert!(!(p < q));
- let mut s = SipHasher::new();
- assert_eq!(p.hash(&mut s), q.hash(&mut s));
-}
-
-#[test]
-fn write_unaligned_drop() {
- thread_local! {
- static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
- }
-
- struct Dropper(u32);
-
- impl Drop for Dropper {
- fn drop(&mut self) {
- DROPS.with(|d| d.borrow_mut().push(self.0));
- }
- }
-
- {
- let c = Dropper(0);
- let mut t = Dropper(1);
- unsafe { write_unaligned(&mut t, c); }
- }
- DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
-}
+++ /dev/null
-// Copyright 2014 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.
-
-fn op1() -> Result<isize, &'static str> { Ok(666) }
-fn op2() -> Result<isize, &'static str> { Err("sadface") }
-
-#[test]
-fn test_and() {
- assert_eq!(op1().and(Ok(667)).unwrap(), 667);
- assert_eq!(op1().and(Err::<i32, &'static str>("bad")).unwrap_err(),
- "bad");
-
- assert_eq!(op2().and(Ok(667)).unwrap_err(), "sadface");
- assert_eq!(op2().and(Err::<i32,&'static str>("bad")).unwrap_err(),
- "sadface");
-}
-
-#[test]
-fn test_and_then() {
- assert_eq!(op1().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap(), 667);
- assert_eq!(op1().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
- "bad");
-
- assert_eq!(op2().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap_err(),
- "sadface");
- assert_eq!(op2().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
- "sadface");
-}
-
-#[test]
-fn test_or() {
- assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666);
- assert_eq!(op1().or(Err("bad")).unwrap(), 666);
-
- assert_eq!(op2().or(Ok::<_, &'static str>(667)).unwrap(), 667);
- assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad");
-}
-
-#[test]
-fn test_or_else() {
- assert_eq!(op1().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 666);
- assert_eq!(op1().or_else(|e| Err::<isize, &'static str>(e)).unwrap(), 666);
-
- assert_eq!(op2().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 667);
- assert_eq!(op2().or_else(|e| Err::<isize, &'static str>(e)).unwrap_err(),
- "sadface");
-}
-
-#[test]
-fn test_impl_map() {
- assert!(Ok::<isize, isize>(1).map(|x| x + 1) == Ok(2));
- assert!(Err::<isize, isize>(1).map(|x| x + 1) == Err(1));
-}
-
-#[test]
-fn test_impl_map_err() {
- assert!(Ok::<isize, isize>(1).map_err(|x| x + 1) == Ok(1));
- assert!(Err::<isize, isize>(1).map_err(|x| x + 1) == Err(2));
-}
-
-#[test]
-fn test_collect() {
- let v: Result<Vec<isize>, ()> = (0..0).map(|_| Ok::<isize, ()>(0)).collect();
- assert!(v == Ok(vec![]));
-
- let v: Result<Vec<isize>, ()> = (0..3).map(|x| Ok::<isize, ()>(x)).collect();
- assert!(v == Ok(vec![0, 1, 2]));
-
- let v: Result<Vec<isize>, isize> = (0..3).map(|x| {
- if x > 1 { Err(x) } else { Ok(x) }
- }).collect();
- assert!(v == Err(2));
-
- // test that it does not take more elements than it needs
- let mut functions: [Box<Fn() -> Result<(), isize>>; 3] =
- [box || Ok(()), box || Err(1), box || panic!()];
-
- let v: Result<Vec<()>, isize> = functions.iter_mut().map(|f| (*f)()).collect();
- assert!(v == Err(1));
-}
-
-#[test]
-fn test_fmt_default() {
- let ok: Result<isize, &'static str> = Ok(100);
- let err: Result<isize, &'static str> = Err("Err");
-
- let s = format!("{:?}", ok);
- assert_eq!(s, "Ok(100)");
- let s = format!("{:?}", err);
- assert_eq!(s, "Err(\"Err\")");
-}
-
-#[test]
-fn test_unwrap_or() {
- let ok: Result<isize, &'static str> = Ok(100);
- let ok_err: Result<isize, &'static str> = Err("Err");
-
- assert_eq!(ok.unwrap_or(50), 100);
- assert_eq!(ok_err.unwrap_or(50), 50);
-}
-
-#[test]
-fn test_unwrap_or_else() {
- fn handler(msg: &'static str) -> isize {
- if msg == "I got this." {
- 50
- } else {
- panic!("BadBad")
- }
- }
-
- let ok: Result<isize, &'static str> = Ok(100);
- let ok_err: Result<isize, &'static str> = Err("I got this.");
-
- assert_eq!(ok.unwrap_or_else(handler), 100);
- assert_eq!(ok_err.unwrap_or_else(handler), 50);
-}
-
-#[test]
-#[should_panic]
-pub fn test_unwrap_or_else_panic() {
- fn handler(msg: &'static str) -> isize {
- if msg == "I got this." {
- 50
- } else {
- panic!("BadBad")
- }
- }
-
- let bad_err: Result<isize, &'static str> = Err("Unrecoverable mess.");
- let _ : isize = bad_err.unwrap_or_else(handler);
-}
-
-
-#[test]
-pub fn test_expect_ok() {
- let ok: Result<isize, &'static str> = Ok(100);
- assert_eq!(ok.expect("Unexpected error"), 100);
-}
-#[test]
-#[should_panic(expected="Got expected error: \"All good\"")]
-pub fn test_expect_err() {
- let err: Result<isize, &'static str> = Err("All good");
- err.expect("Got expected error");
-}
-
-
-#[test]
-pub fn test_expect_err_err() {
- let ok: Result<&'static str, isize> = Err(100);
- assert_eq!(ok.expect_err("Unexpected ok"), 100);
-}
-#[test]
-#[should_panic(expected="Got expected ok: \"All good\"")]
-pub fn test_expect_err_ok() {
- let err: Result<&'static str, isize> = Ok("All good");
- err.expect_err("Got expected ok");
-}
-
-#[test]
-pub fn test_iter() {
- let ok: Result<isize, &'static str> = Ok(100);
- let mut it = ok.iter();
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(it.next(), Some(&100));
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert!(it.next().is_none());
- assert_eq!((&ok).into_iter().next(), Some(&100));
-
- let err: Result<isize, &'static str> = Err("error");
- assert_eq!(err.iter().next(), None);
-}
-
-#[test]
-pub fn test_iter_mut() {
- let mut ok: Result<isize, &'static str> = Ok(100);
- for loc in ok.iter_mut() {
- *loc = 200;
- }
- assert_eq!(ok, Ok(200));
- for loc in &mut ok {
- *loc = 300;
- }
- assert_eq!(ok, Ok(300));
-
- let mut err: Result<isize, &'static str> = Err("error");
- for loc in err.iter_mut() {
- *loc = 200;
- }
- assert_eq!(err, Err("error"));
-}
-
-#[test]
-pub fn test_unwrap_or_default() {
- assert_eq!(op1().unwrap_or_default(), 666);
- assert_eq!(op2().unwrap_or_default(), 0);
-}
+++ /dev/null
-// Copyright 2014 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.
-
-use core::cmp::Ordering::{Equal, Greater, Less};
-use core::slice::heapsort;
-use core::result::Result::{Ok, Err};
-use rand::{Rng, XorShiftRng};
-
-#[test]
-fn test_binary_search() {
- let b = [1, 2, 4, 6, 8, 9];
- assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
- assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
- let b = [1, 2, 4, 6, 7, 8, 9];
- assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
- assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
- let b = [1, 2, 4, 6, 8, 9];
- assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(4));
- assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(4));
- let b = [1, 2, 4, 6, 7, 8, 9];
- assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(5));
- let b = [1, 2, 4, 5, 6, 8, 9];
- assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(5));
- assert!(b.binary_search_by(|v| v.cmp(&0)) == Err(0));
- let b = [1, 2, 4, 5, 6, 8];
- assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6));
-}
-
-#[test]
-fn test_iterator_nth() {
- let v: &[_] = &[0, 1, 2, 3, 4];
- for i in 0..v.len() {
- assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
- }
- assert_eq!(v.iter().nth(v.len()), None);
-
- let mut iter = v.iter();
- assert_eq!(iter.nth(2).unwrap(), &v[2]);
- assert_eq!(iter.nth(1).unwrap(), &v[4]);
-}
-
-#[test]
-fn test_iterator_last() {
- let v: &[_] = &[0, 1, 2, 3, 4];
- assert_eq!(v.iter().last().unwrap(), &4);
- assert_eq!(v[..1].iter().last().unwrap(), &0);
-}
-
-#[test]
-fn test_iterator_count() {
- let v: &[_] = &[0, 1, 2, 3, 4];
- assert_eq!(v.iter().count(), 5);
-
- let mut iter2 = v.iter();
- iter2.next();
- iter2.next();
- assert_eq!(iter2.count(), 3);
-}
-
-#[test]
-fn test_chunks_count() {
- let v: &[i32] = &[0, 1, 2, 3, 4, 5];
- let c = v.chunks(3);
- assert_eq!(c.count(), 2);
-
- let v2: &[i32] = &[0, 1, 2, 3, 4];
- let c2 = v2.chunks(2);
- assert_eq!(c2.count(), 3);
-
- let v3: &[i32] = &[];
- let c3 = v3.chunks(2);
- assert_eq!(c3.count(), 0);
-}
-
-#[test]
-fn test_chunks_nth() {
- let v: &[i32] = &[0, 1, 2, 3, 4, 5];
- let mut c = v.chunks(2);
- assert_eq!(c.nth(1).unwrap()[1], 3);
- assert_eq!(c.next().unwrap()[0], 4);
-
- let v2: &[i32] = &[0, 1, 2, 3, 4];
- let mut c2 = v2.chunks(3);
- assert_eq!(c2.nth(1).unwrap()[1], 4);
- assert_eq!(c2.next(), None);
-}
-
-#[test]
-fn test_chunks_last() {
- let v: &[i32] = &[0, 1, 2, 3, 4, 5];
- let c = v.chunks(2);
- assert_eq!(c.last().unwrap()[1], 5);
-
- let v2: &[i32] = &[0, 1, 2, 3, 4];
- let c2 = v2.chunks(2);
- assert_eq!(c2.last().unwrap()[0], 4);
-}
-
-#[test]
-fn test_chunks_mut_count() {
- let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
- let c = v.chunks_mut(3);
- assert_eq!(c.count(), 2);
-
- let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
- let c2 = v2.chunks_mut(2);
- assert_eq!(c2.count(), 3);
-
- let mut v3: &mut [i32] = &mut [];
- let c3 = v3.chunks_mut(2);
- assert_eq!(c3.count(), 0);
-}
-
-#[test]
-fn test_chunks_mut_nth() {
- let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
- let mut c = v.chunks_mut(2);
- assert_eq!(c.nth(1).unwrap()[1], 3);
- assert_eq!(c.next().unwrap()[0], 4);
-
- let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
- let mut c2 = v2.chunks_mut(3);
- assert_eq!(c2.nth(1).unwrap()[1], 4);
- assert_eq!(c2.next(), None);
-}
-
-#[test]
-fn test_chunks_mut_last() {
- let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
- let c = v.chunks_mut(2);
- assert_eq!(c.last().unwrap()[1], 5);
-
- let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
- let c2 = v2.chunks_mut(2);
- assert_eq!(c2.last().unwrap()[0], 4);
-}
-
-#[test]
-fn test_windows_count() {
- let v: &[i32] = &[0, 1, 2, 3, 4, 5];
- let c = v.windows(3);
- assert_eq!(c.count(), 4);
-
- let v2: &[i32] = &[0, 1, 2, 3, 4];
- let c2 = v2.windows(6);
- assert_eq!(c2.count(), 0);
-
- let v3: &[i32] = &[];
- let c3 = v3.windows(2);
- assert_eq!(c3.count(), 0);
-}
-
-#[test]
-fn test_windows_nth() {
- let v: &[i32] = &[0, 1, 2, 3, 4, 5];
- let mut c = v.windows(2);
- assert_eq!(c.nth(2).unwrap()[1], 3);
- assert_eq!(c.next().unwrap()[0], 3);
-
- let v2: &[i32] = &[0, 1, 2, 3, 4];
- let mut c2 = v2.windows(4);
- assert_eq!(c2.nth(1).unwrap()[1], 2);
- assert_eq!(c2.next(), None);
-}
-
-#[test]
-fn test_windows_last() {
- let v: &[i32] = &[0, 1, 2, 3, 4, 5];
- let c = v.windows(2);
- assert_eq!(c.last().unwrap()[1], 5);
-
- let v2: &[i32] = &[0, 1, 2, 3, 4];
- let c2 = v2.windows(2);
- assert_eq!(c2.last().unwrap()[0], 3);
-}
-
-#[test]
-fn get_range() {
- let v: &[i32] = &[0, 1, 2, 3, 4, 5];
- assert_eq!(v.get(..), Some(&[0, 1, 2, 3, 4, 5][..]));
- assert_eq!(v.get(..2), Some(&[0, 1][..]));
- assert_eq!(v.get(2..), Some(&[2, 3, 4, 5][..]));
- assert_eq!(v.get(1..4), Some(&[1, 2, 3][..]));
- assert_eq!(v.get(7..), None);
- assert_eq!(v.get(7..10), None);
-}
-
-#[test]
-fn get_mut_range() {
- let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
- assert_eq!(v.get_mut(..), Some(&mut [0, 1, 2, 3, 4, 5][..]));
- assert_eq!(v.get_mut(..2), Some(&mut [0, 1][..]));
- assert_eq!(v.get_mut(2..), Some(&mut [2, 3, 4, 5][..]));
- assert_eq!(v.get_mut(1..4), Some(&mut [1, 2, 3][..]));
- assert_eq!(v.get_mut(7..), None);
- assert_eq!(v.get_mut(7..10), None);
-}
-
-#[test]
-fn get_unchecked_range() {
- unsafe {
- let v: &[i32] = &[0, 1, 2, 3, 4, 5];
- assert_eq!(v.get_unchecked(..), &[0, 1, 2, 3, 4, 5][..]);
- assert_eq!(v.get_unchecked(..2), &[0, 1][..]);
- assert_eq!(v.get_unchecked(2..), &[2, 3, 4, 5][..]);
- assert_eq!(v.get_unchecked(1..4), &[1, 2, 3][..]);
- }
-}
-
-#[test]
-fn get_unchecked_mut_range() {
- unsafe {
- let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
- assert_eq!(v.get_unchecked_mut(..), &mut [0, 1, 2, 3, 4, 5][..]);
- assert_eq!(v.get_unchecked_mut(..2), &mut [0, 1][..]);
- assert_eq!(v.get_unchecked_mut(2..), &mut[2, 3, 4, 5][..]);
- assert_eq!(v.get_unchecked_mut(1..4), &mut [1, 2, 3][..]);
- }
-}
-
-#[test]
-fn sort_unstable() {
- let mut v = [0; 600];
- let mut tmp = [0; 600];
- let mut rng = XorShiftRng::new_unseeded();
-
- for len in (2..25).chain(500..510) {
- let v = &mut v[0..len];
- let tmp = &mut tmp[0..len];
-
- for &modulus in &[5, 10, 100, 1000] {
- for _ in 0..100 {
- for i in 0..len {
- v[i] = rng.gen::<i32>() % modulus;
- }
-
- // Sort in default order.
- tmp.copy_from_slice(v);
- tmp.sort_unstable();
- assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
-
- // Sort in ascending order.
- tmp.copy_from_slice(v);
- tmp.sort_unstable_by(|a, b| a.cmp(b));
- assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
-
- // Sort in descending order.
- tmp.copy_from_slice(v);
- tmp.sort_unstable_by(|a, b| b.cmp(a));
- assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
-
- // Test heapsort using `<` operator.
- tmp.copy_from_slice(v);
- heapsort(tmp, |a, b| a < b);
- assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
-
- // Test heapsort using `>` operator.
- tmp.copy_from_slice(v);
- heapsort(tmp, |a, b| a > b);
- assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
- }
- }
- }
-
- // Sort using a completely random comparison function.
- // This will reorder the elements *somehow*, but won't panic.
- for i in 0..v.len() {
- v[i] = i as i32;
- }
- v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap());
- v.sort_unstable();
- for i in 0..v.len() {
- assert_eq!(v[i], i as i32);
- }
-
- // Should not panic.
- [0i32; 0].sort_unstable();
- [(); 10].sort_unstable();
- [(); 100].sort_unstable();
-
- let mut v = [0xDEADBEEFu64];
- v.sort_unstable();
- assert!(v == [0xDEADBEEF]);
-}
+++ /dev/null
-// Copyright 2014-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.
-
-// All `str` tests live in libcollectiontest::str
+++ /dev/null
-// Copyright 2014 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.
-
-use std::cmp::Ordering::{Equal, Less, Greater};
-
-#[test]
-fn test_clone() {
- let a = (1, "2");
- let b = a.clone();
- assert_eq!(a, b);
-}
-
-#[test]
-fn test_tuple_cmp() {
- let (small, big) = ((1, 2, 3), (3, 2, 1));
-
- let nan = 0.0f64/0.0;
-
- // PartialEq
- assert_eq!(small, small);
- assert_eq!(big, big);
- assert!(small != big);
- assert!(big != small);
-
- // PartialOrd
- assert!(small < big);
- assert!(!(small < small));
- assert!(!(big < small));
- assert!(!(big < big));
-
- assert!(small <= small);
- assert!(big <= big);
-
- assert!(big > small);
- assert!(small >= small);
- assert!(big >= small);
- assert!(big >= big);
-
- assert!(!((1.0f64, 2.0f64) < (nan, 3.0)));
- assert!(!((1.0f64, 2.0f64) <= (nan, 3.0)));
- assert!(!((1.0f64, 2.0f64) > (nan, 3.0)));
- assert!(!((1.0f64, 2.0f64) >= (nan, 3.0)));
- assert!(((1.0f64, 2.0f64) < (2.0, nan)));
- assert!(!((2.0f64, 2.0f64) < (2.0, nan)));
-
- // Ord
- assert!(small.cmp(&small) == Equal);
- assert!(big.cmp(&big) == Equal);
- assert!(small.cmp(&big) == Less);
- assert!(big.cmp(&small) == Greater);
-}
-
-#[test]
-fn test_show() {
- let s = format!("{:?}", (1,));
- assert_eq!(s, "(1,)");
- let s = format!("{:?}", (1, true));
- assert_eq!(s, "(1, true)");
- let s = format!("{:?}", (1, "hi", true));
- assert_eq!(s, "(1, \"hi\", true)");
-}
}
}
+ pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
+ self.node_to_hir_id[node_id]
+ }
+
/// Add a definition with a parent definition.
pub fn create_def_with_parent(&mut self,
parent: Option<DefIndex>,
--- /dev/null
+// Copyright 2017 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.
+
+use hir;
+use hir::def_id::DefId;
+use ich::{self, CachingCodemapView, DefPathHashes};
+use session::config::DebugInfoLevel::NoDebugInfo;
+use ty;
+
+use std::hash as std_hash;
+
+use syntax::ast;
+use syntax::attr;
+use syntax::ext::hygiene::SyntaxContext;
+use syntax::symbol::Symbol;
+use syntax_pos::Span;
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+ StableHasherResult};
+use rustc_data_structures::accumulate_vec::AccumulateVec;
+
+/// This is the context state available during incr. comp. hashing. It contains
+/// enough information to transform DefIds and HirIds into stable DefPaths (i.e.
+/// a reference to the TyCtxt) and it holds a few caches for speeding up various
+/// things (e.g. each DefId/DefPath is only hashed once).
+pub struct StableHashingContext<'a, 'tcx: 'a> {
+ tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+ def_path_hashes: DefPathHashes<'a, 'tcx>,
+ codemap: CachingCodemapView<'tcx>,
+ hash_spans: bool,
+ hash_bodies: bool,
+ overflow_checks_enabled: bool,
+ node_id_hashing_mode: NodeIdHashingMode,
+ // A sorted array of symbol keys for fast lookup.
+ ignored_attr_names: Vec<Symbol>,
+}
+
+#[derive(PartialEq, Eq, Clone, Copy)]
+pub enum NodeIdHashingMode {
+ Ignore,
+ HashDefPath,
+ HashTraitsInScope,
+}
+
+impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> {
+
+ pub fn new(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Self {
+ let hash_spans_initial = tcx.sess.opts.debuginfo != NoDebugInfo;
+ let check_overflow_initial = tcx.sess.overflow_checks();
+
+ let mut ignored_attr_names: Vec<_> = ich::IGNORED_ATTRIBUTES
+ .iter()
+ .map(|&s| Symbol::intern(s))
+ .collect();
+
+ ignored_attr_names.sort();
+
+ StableHashingContext {
+ tcx: tcx,
+ def_path_hashes: DefPathHashes::new(tcx),
+ codemap: CachingCodemapView::new(tcx),
+ hash_spans: hash_spans_initial,
+ hash_bodies: true,
+ overflow_checks_enabled: check_overflow_initial,
+ node_id_hashing_mode: NodeIdHashingMode::HashDefPath,
+ ignored_attr_names: ignored_attr_names,
+ }
+ }
+
+ #[inline]
+ pub fn while_hashing_hir_bodies<F: FnOnce(&mut Self)>(&mut self,
+ hash_bodies: bool,
+ f: F) {
+ let prev_hash_bodies = self.hash_bodies;
+ self.hash_bodies = hash_bodies;
+ f(self);
+ self.hash_bodies = prev_hash_bodies;
+ }
+
+ #[inline]
+ pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self,
+ hash_spans: bool,
+ f: F) {
+ let prev_hash_spans = self.hash_spans;
+ self.hash_spans = hash_spans;
+ f(self);
+ self.hash_spans = prev_hash_spans;
+ }
+
+ #[inline]
+ pub fn with_node_id_hashing_mode<F: FnOnce(&mut Self)>(&mut self,
+ mode: NodeIdHashingMode,
+ f: F) {
+ let prev = self.node_id_hashing_mode;
+ self.node_id_hashing_mode = mode;
+ f(self);
+ self.node_id_hashing_mode = prev;
+ }
+
+ #[inline]
+ pub fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> {
+ self.tcx
+ }
+
+ #[inline]
+ pub fn def_path_hash(&mut self, def_id: DefId) -> u64 {
+ self.def_path_hashes.hash(def_id)
+ }
+
+ #[inline]
+ pub fn hash_spans(&self) -> bool {
+ self.hash_spans
+ }
+
+ #[inline]
+ pub fn hash_bodies(&self) -> bool {
+ self.hash_bodies
+ }
+
+ #[inline]
+ pub fn codemap(&mut self) -> &mut CachingCodemapView<'tcx> {
+ &mut self.codemap
+ }
+
+ #[inline]
+ pub fn is_ignored_attr(&self, name: Symbol) -> bool {
+ self.ignored_attr_names.binary_search(&name).is_ok()
+ }
+
+ pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self,
+ item_attrs: &[ast::Attribute],
+ f: F) {
+ let prev_overflow_checks = self.overflow_checks_enabled;
+ if attr::contains_name(item_attrs, "rustc_inherit_overflow_checks") {
+ self.overflow_checks_enabled = true;
+ }
+ let prev_hash_node_ids = self.node_id_hashing_mode;
+ self.node_id_hashing_mode = NodeIdHashingMode::Ignore;
+
+ f(self);
+
+ self.node_id_hashing_mode = prev_hash_node_ids;
+ self.overflow_checks_enabled = prev_overflow_checks;
+ }
+
+ #[inline]
+ pub fn binop_can_panic_at_runtime(&self, binop: hir::BinOp_) -> bool
+ {
+ match binop {
+ hir::BiAdd |
+ hir::BiSub |
+ hir::BiMul => self.overflow_checks_enabled,
+
+ hir::BiDiv |
+ hir::BiRem => true,
+
+ hir::BiAnd |
+ hir::BiOr |
+ hir::BiBitXor |
+ hir::BiBitAnd |
+ hir::BiBitOr |
+ hir::BiShl |
+ hir::BiShr |
+ hir::BiEq |
+ hir::BiLt |
+ hir::BiLe |
+ hir::BiNe |
+ hir::BiGe |
+ hir::BiGt => false
+ }
+ }
+
+ #[inline]
+ pub fn unop_can_panic_at_runtime(&self, unop: hir::UnOp) -> bool
+ {
+ match unop {
+ hir::UnDeref |
+ hir::UnNot => false,
+ hir::UnNeg => self.overflow_checks_enabled,
+ }
+ }
+}
+
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::NodeId {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ match hcx.node_id_hashing_mode {
+ NodeIdHashingMode::Ignore => {
+ // Most NodeIds in the HIR can be ignored, but if there is a
+ // corresponding entry in the `trait_map` we need to hash that.
+ // Make sure we don't ignore too much by checking that there is
+ // no entry in a debug_assert!().
+ debug_assert!(hcx.tcx.trait_map.get(self).is_none());
+ }
+ NodeIdHashingMode::HashDefPath => {
+ hcx.tcx.hir.definitions().node_to_hir_id(*self).hash_stable(hcx, hasher);
+ }
+ NodeIdHashingMode::HashTraitsInScope => {
+ if let Some(traits) = hcx.tcx.trait_map.get(self) {
+ // The ordering of the candidates is not fixed. So we hash
+ // the def-ids and then sort them and hash the collection.
+ let mut candidates: AccumulateVec<[_; 8]> =
+ traits.iter()
+ .map(|&hir::TraitCandidate { def_id, import_id: _ }| {
+ hcx.def_path_hash(def_id)
+ })
+ .collect();
+ if traits.len() > 1 {
+ candidates.sort();
+ }
+ candidates.hash_stable(hcx, hasher);
+ }
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for Span {
+
+ // Hash a span in a stable way. We can't directly hash the span's BytePos
+ // fields (that would be similar to hashing pointers, since those are just
+ // offsets into the CodeMap). Instead, we hash the (file name, line, column)
+ // triple, which stays the same even if the containing FileMap has moved
+ // within the CodeMap.
+ // Also note that we are hashing byte offsets for the column, not unicode
+ // codepoint offsets. For the purpose of the hash that's sufficient.
+ // Also, hashing filenames is expensive so we avoid doing it twice when the
+ // span starts and ends in the same file, which is almost always the case.
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ use syntax_pos::Pos;
+
+ if !hcx.hash_spans {
+ return
+ }
+
+ // If this is not an empty or invalid span, we want to hash the last
+ // position that belongs to it, as opposed to hashing the first
+ // position past it.
+ let span_hi = if self.hi > self.lo {
+ // We might end up in the middle of a multibyte character here,
+ // but that's OK, since we are not trying to decode anything at
+ // this position.
+ self.hi - ::syntax_pos::BytePos(1)
+ } else {
+ self.hi
+ };
+
+ {
+ let loc1 = hcx.codemap().byte_pos_to_line_and_col(self.lo);
+ let loc1 = loc1.as_ref()
+ .map(|&(ref fm, line, col)| (&fm.name[..], line, col.to_usize()))
+ .unwrap_or(("???", 0, 0));
+
+ let loc2 = hcx.codemap().byte_pos_to_line_and_col(span_hi);
+ let loc2 = loc2.as_ref()
+ .map(|&(ref fm, line, col)| (&fm.name[..], line, col.to_usize()))
+ .unwrap_or(("???", 0, 0));
+
+ if loc1.0 == loc2.0 {
+ std_hash::Hash::hash(&0u8, hasher);
+
+ std_hash::Hash::hash(loc1.0, hasher);
+ std_hash::Hash::hash(&loc1.1, hasher);
+ std_hash::Hash::hash(&loc1.2, hasher);
+
+ // Do not hash the file name twice
+ std_hash::Hash::hash(&loc2.1, hasher);
+ std_hash::Hash::hash(&loc2.2, hasher);
+ } else {
+ std_hash::Hash::hash(&1u8, hasher);
+
+ std_hash::Hash::hash(loc1.0, hasher);
+ std_hash::Hash::hash(&loc1.1, hasher);
+ std_hash::Hash::hash(&loc1.2, hasher);
+
+ std_hash::Hash::hash(loc2.0, hasher);
+ std_hash::Hash::hash(&loc2.1, hasher);
+ std_hash::Hash::hash(&loc2.2, hasher);
+ }
+ }
+
+ if self.ctxt == SyntaxContext::empty() {
+ 0u8.hash_stable(hcx, hasher);
+ } else {
+ 1u8.hash_stable(hcx, hasher);
+ self.source_callsite().hash_stable(hcx, hasher);
+ }
+ }
+}
--- /dev/null
+// Copyright 2017 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.
+
+//! This module contains `HashStable` implementations for various data types
+//! from `rustc_const_math` in no particular order.
+
+impl_stable_hash_for!(enum ::rustc_const_math::ConstFloat {
+ F32(val),
+ F64(val)
+});
+
+impl_stable_hash_for!(enum ::rustc_const_math::ConstInt {
+ I8(val),
+ I16(val),
+ I32(val),
+ I64(val),
+ I128(val),
+ Isize(val),
+ U8(val),
+ U16(val),
+ U32(val),
+ U64(val),
+ U128(val),
+ Usize(val)
+});
+
+impl_stable_hash_for!(enum ::rustc_const_math::ConstIsize {
+ Is16(i16),
+ Is32(i32),
+ Is64(i64)
+});
+
+impl_stable_hash_for!(enum ::rustc_const_math::ConstUsize {
+ Us16(i16),
+ Us32(i32),
+ Us64(i64)
+});
+
+impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr {
+ NotInRange,
+ CmpBetweenUnequalTypes,
+ UnequalTypes(op),
+ Overflow(op),
+ ShiftNegative,
+ DivisionByZero,
+ RemainderByZero,
+ UnsignedNegation,
+ ULitOutOfRange(int_ty),
+ LitOutOfRange(int_ty)
+});
+
+impl_stable_hash_for!(enum ::rustc_const_math::Op {
+ Add,
+ Sub,
+ Mul,
+ Div,
+ Rem,
+ Shr,
+ Shl,
+ Neg,
+ BitAnd,
+ BitOr,
+ BitXor
+});
--- /dev/null
+// Copyright 2017 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.
+
+//! This module contains `HashStable` implementations for various HIR data
+//! types in no particular order.
+
+use hir;
+use hir::def_id::DefId;
+use ich::{StableHashingContext, NodeIdHashingMode};
+use std::mem;
+
+use syntax::ast;
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+ StableHasherResult};
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for DefId {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ hcx.def_path_hash(*self).hash_stable(hcx, hasher);
+ }
+}
+
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::HirId {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let hir::HirId {
+ owner,
+ local_id,
+ } = *self;
+
+ hcx.def_path_hash(DefId::local(owner)).hash_stable(hcx, hasher);
+ local_id.hash_stable(hcx, hasher);
+ }
+}
+
+impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index });
+
+// The following implementations of HashStable for ItemId, TraitItemId, and
+// ImplItemId deserve special attention. Normally we do not hash NodeIds within
+// the HIR, since they just signify a HIR nodes own path. But ItemId et al
+// are used when another item in the HIR is *referenced* and we certainly
+// want to pick up on a reference changing its target, so we hash the NodeIds
+// in "DefPath Mode".
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::ItemId {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let hir::ItemId {
+ id
+ } = *self;
+
+ hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+ id.hash_stable(hcx, hasher);
+ })
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::TraitItemId {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let hir::TraitItemId {
+ node_id
+ } = * self;
+
+ hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+ node_id.hash_stable(hcx, hasher);
+ })
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::ImplItemId {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let hir::ImplItemId {
+ node_id
+ } = * self;
+
+ hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+ node_id.hash_stable(hcx, hasher);
+ })
+ }
+}
+
+impl_stable_hash_for!(struct hir::Lifetime {
+ id,
+ span,
+ name
+});
+
+impl_stable_hash_for!(struct hir::LifetimeDef {
+ lifetime,
+ bounds,
+ pure_wrt_drop
+});
+
+impl_stable_hash_for!(struct hir::Path {
+ span,
+ def,
+ segments
+});
+
+impl_stable_hash_for!(struct hir::PathSegment {
+ name,
+ parameters
+});
+
+impl_stable_hash_for!(enum hir::PathParameters {
+ AngleBracketedParameters(data),
+ ParenthesizedParameters(data)
+});
+
+impl_stable_hash_for!(struct hir::AngleBracketedParameterData {
+ lifetimes,
+ types,
+ infer_types,
+ bindings
+});
+
+impl_stable_hash_for!(struct hir::ParenthesizedParameterData {
+ span,
+ inputs,
+ output
+});
+
+impl_stable_hash_for!(enum hir::TyParamBound {
+ TraitTyParamBound(poly_trait_ref, trait_bound_modifier),
+ RegionTyParamBound(lifetime)
+});
+
+impl_stable_hash_for!(enum hir::TraitBoundModifier {
+ None,
+ Maybe
+});
+
+impl_stable_hash_for!(struct hir::TyParam {
+ name,
+ id,
+ bounds,
+ default,
+ span,
+ pure_wrt_drop
+});
+
+impl_stable_hash_for!(struct hir::Generics {
+ lifetimes,
+ ty_params,
+ where_clause,
+ span
+});
+
+impl_stable_hash_for!(struct hir::WhereClause {
+ id,
+ predicates
+});
+
+impl_stable_hash_for!(enum hir::WherePredicate {
+ BoundPredicate(pred),
+ RegionPredicate(pred),
+ EqPredicate(pred)
+});
+
+impl_stable_hash_for!(struct hir::WhereBoundPredicate {
+ span,
+ bound_lifetimes,
+ bounded_ty,
+ bounds
+});
+
+impl_stable_hash_for!(struct hir::WhereRegionPredicate {
+ span,
+ lifetime,
+ bounds
+});
+
+impl_stable_hash_for!(struct hir::WhereEqPredicate {
+ id,
+ span,
+ lhs_ty,
+ rhs_ty
+});
+
+impl_stable_hash_for!(struct hir::MutTy {
+ ty,
+ mutbl
+});
+
+impl_stable_hash_for!(struct hir::MethodSig {
+ unsafety,
+ constness,
+ abi,
+ decl,
+ generics
+});
+
+impl_stable_hash_for!(struct hir::TypeBinding {
+ id,
+ name,
+ ty,
+ span
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Ty {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let node_id_hashing_mode = match self.node {
+ hir::TySlice(..) |
+ hir::TyArray(..) |
+ hir::TyPtr(..) |
+ hir::TyRptr(..) |
+ hir::TyBareFn(..) |
+ hir::TyNever |
+ hir::TyTup(..) |
+ hir::TyTraitObject(..) |
+ hir::TyImplTrait(..) |
+ hir::TyTypeof(..) |
+ hir::TyInfer => {
+ NodeIdHashingMode::Ignore
+ }
+ hir::TyPath(..) => {
+ NodeIdHashingMode::HashTraitsInScope
+ }
+ };
+
+ hcx.while_hashing_hir_bodies(true, |hcx| {
+ let hir::Ty {
+ id,
+ ref node,
+ ref span,
+ } = *self;
+
+ hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
+ id.hash_stable(hcx, hasher);
+ });
+ node.hash_stable(hcx, hasher);
+ span.hash_stable(hcx, hasher);
+ })
+ }
+}
+
+impl_stable_hash_for!(enum hir::PrimTy {
+ TyInt(int_ty),
+ TyUint(uint_ty),
+ TyFloat(float_ty),
+ TyStr,
+ TyBool,
+ TyChar
+});
+
+impl_stable_hash_for!(struct hir::BareFnTy {
+ unsafety,
+ abi,
+ lifetimes,
+ decl
+});
+
+impl_stable_hash_for!(enum hir::Ty_ {
+ TySlice(t),
+ TyArray(t, body_id),
+ TyPtr(t),
+ TyRptr(lifetime, t),
+ TyBareFn(t),
+ TyNever,
+ TyTup(ts),
+ TyPath(qpath),
+ TyTraitObject(trait_refs, lifetime),
+ TyImplTrait(bounds),
+ TyTypeof(body_id),
+ TyInfer
+});
+
+impl_stable_hash_for!(struct hir::FnDecl {
+ inputs,
+ output,
+ variadic,
+ has_implicit_self
+});
+
+impl_stable_hash_for!(enum hir::FunctionRetTy {
+ DefaultReturn(span),
+ Return(t)
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::TraitRef {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let hir::TraitRef {
+ ref path,
+ ref_id,
+ } = *self;
+
+ path.hash_stable(hcx, hasher);
+ hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashTraitsInScope, |hcx| {
+ ref_id.hash_stable(hcx, hasher);
+ });
+ }
+}
+
+
+impl_stable_hash_for!(struct hir::PolyTraitRef {
+ bound_lifetimes,
+ trait_ref,
+ span
+});
+
+impl_stable_hash_for!(enum hir::QPath {
+ Resolved(t, path),
+ TypeRelative(t, path_segment)
+});
+
+impl_stable_hash_for!(struct hir::MacroDef {
+ name,
+ attrs,
+ id,
+ span,
+ body
+});
+
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Block {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let hir::Block {
+ ref stmts,
+ ref expr,
+ id,
+ rules,
+ span,
+ targeted_by_break,
+ } = *self;
+
+ let non_item_stmts = || stmts.iter().filter(|stmt| {
+ match stmt.node {
+ hir::StmtDecl(ref decl, _) => {
+ match decl.node {
+ // If this is a declaration of a nested item, we don't
+ // want to leave any trace of it in the hash value, not
+ // even that it exists. Otherwise changing the position
+ // of nested items would invalidate the containing item
+ // even though that does not constitute a semantic
+ // change.
+ hir::DeclItem(_) => false,
+ hir::DeclLocal(_) => true
+ }
+ }
+ hir::StmtExpr(..) |
+ hir::StmtSemi(..) => true
+ }
+ });
+
+ let count = non_item_stmts().count();
+
+ count.hash_stable(hcx, hasher);
+
+ for stmt in non_item_stmts() {
+ stmt.hash_stable(hcx, hasher);
+ }
+
+ expr.hash_stable(hcx, hasher);
+ id.hash_stable(hcx, hasher);
+ rules.hash_stable(hcx, hasher);
+ span.hash_stable(hcx, hasher);
+ targeted_by_break.hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Pat {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let node_id_hashing_mode = match self.node {
+ hir::PatKind::Wild |
+ hir::PatKind::Binding(..) |
+ hir::PatKind::Tuple(..) |
+ hir::PatKind::Box(..) |
+ hir::PatKind::Ref(..) |
+ hir::PatKind::Lit(..) |
+ hir::PatKind::Range(..) |
+ hir::PatKind::Slice(..) => {
+ NodeIdHashingMode::Ignore
+ }
+ hir::PatKind::Path(..) |
+ hir::PatKind::Struct(..) |
+ hir::PatKind::TupleStruct(..) => {
+ NodeIdHashingMode::HashTraitsInScope
+ }
+ };
+
+ let hir::Pat {
+ id,
+ ref node,
+ ref span
+ } = *self;
+
+ hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
+ id.hash_stable(hcx, hasher);
+ });
+ node.hash_stable(hcx, hasher);
+ span.hash_stable(hcx, hasher);
+ }
+}
+
+impl_stable_hash_for_spanned!(hir::FieldPat);
+impl_stable_hash_for!(struct hir::FieldPat {
+ name,
+ pat,
+ is_shorthand
+});
+
+impl_stable_hash_for!(enum hir::BindingMode {
+ BindByRef(mutability),
+ BindByValue(mutability)
+});
+
+impl_stable_hash_for!(enum hir::RangeEnd {
+ Included,
+ Excluded
+});
+
+impl_stable_hash_for!(enum hir::PatKind {
+ Wild,
+ Binding(binding_mode, var, name, sub),
+ Struct(path, field_pats, dotdot),
+ TupleStruct(path, field_pats, dotdot),
+ Path(path),
+ Tuple(field_pats, dotdot),
+ Box(sub),
+ Ref(sub, mutability),
+ Lit(expr),
+ Range(start, end, end_kind),
+ Slice(one, two, three)
+});
+
+impl_stable_hash_for!(enum hir::BinOp_ {
+ BiAdd,
+ BiSub,
+ BiMul,
+ BiDiv,
+ BiRem,
+ BiAnd,
+ BiOr,
+ BiBitXor,
+ BiBitAnd,
+ BiBitOr,
+ BiShl,
+ BiShr,
+ BiEq,
+ BiLt,
+ BiLe,
+ BiNe,
+ BiGe,
+ BiGt
+});
+
+impl_stable_hash_for_spanned!(hir::BinOp_);
+
+impl_stable_hash_for!(enum hir::UnOp {
+ UnDeref,
+ UnNot,
+ UnNeg
+});
+
+impl_stable_hash_for_spanned!(hir::Stmt_);
+
+impl_stable_hash_for!(struct hir::Local {
+ pat,
+ ty,
+ init,
+ id,
+ span,
+ attrs
+});
+
+impl_stable_hash_for_spanned!(hir::Decl_);
+impl_stable_hash_for!(enum hir::Decl_ {
+ DeclLocal(local),
+ DeclItem(item_id)
+});
+
+impl_stable_hash_for!(struct hir::Arm {
+ attrs,
+ pats,
+ guard,
+ body
+});
+
+impl_stable_hash_for!(struct hir::Field {
+ name,
+ expr,
+ span,
+ is_shorthand
+});
+
+impl_stable_hash_for_spanned!(ast::Name);
+
+
+impl_stable_hash_for!(enum hir::BlockCheckMode {
+ DefaultBlock,
+ UnsafeBlock(src),
+ PushUnsafeBlock(src),
+ PopUnsafeBlock(src)
+});
+
+impl_stable_hash_for!(enum hir::UnsafeSource {
+ CompilerGenerated,
+ UserProvided
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Expr {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ hcx.while_hashing_hir_bodies(true, |hcx| {
+ let hir::Expr {
+ id,
+ ref span,
+ ref node,
+ ref attrs
+ } = *self;
+
+ let (spans_always_on, node_id_hashing_mode) = match *node {
+ hir::ExprBox(..) |
+ hir::ExprArray(..) |
+ hir::ExprCall(..) |
+ hir::ExprLit(..) |
+ hir::ExprCast(..) |
+ hir::ExprType(..) |
+ hir::ExprIf(..) |
+ hir::ExprWhile(..) |
+ hir::ExprLoop(..) |
+ hir::ExprMatch(..) |
+ hir::ExprClosure(..) |
+ hir::ExprBlock(..) |
+ hir::ExprAssign(..) |
+ hir::ExprTupField(..) |
+ hir::ExprAddrOf(..) |
+ hir::ExprBreak(..) |
+ hir::ExprAgain(..) |
+ hir::ExprRet(..) |
+ hir::ExprInlineAsm(..) |
+ hir::ExprRepeat(..) |
+ hir::ExprTup(..) => {
+ // For these we only hash the span when debuginfo is on.
+ (false, NodeIdHashingMode::Ignore)
+ }
+ // For the following, spans might be significant because of
+ // panic messages indicating the source location.
+ hir::ExprBinary(op, ..) => {
+ (hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::Ignore)
+ }
+ hir::ExprUnary(op, _) => {
+ (hcx.unop_can_panic_at_runtime(op), NodeIdHashingMode::Ignore)
+ }
+ hir::ExprAssignOp(op, ..) => {
+ (hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::Ignore)
+ }
+ hir::ExprIndex(..) => {
+ (true, NodeIdHashingMode::Ignore)
+ }
+ // For these we don't care about the span, but want to hash the
+ // trait in scope
+ hir::ExprMethodCall(..) |
+ hir::ExprPath(..) |
+ hir::ExprStruct(..) |
+ hir::ExprField(..) => {
+ (false, NodeIdHashingMode::HashTraitsInScope)
+ }
+ };
+
+ hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
+ id.hash_stable(hcx, hasher);
+ });
+
+ if spans_always_on {
+ hcx.while_hashing_spans(true, |hcx| {
+ span.hash_stable(hcx, hasher);
+ node.hash_stable(hcx, hasher);
+ attrs.hash_stable(hcx, hasher);
+ });
+ } else {
+ span.hash_stable(hcx, hasher);
+ node.hash_stable(hcx, hasher);
+ attrs.hash_stable(hcx, hasher);
+ }
+ })
+ }
+}
+
+impl_stable_hash_for!(enum hir::Expr_ {
+ ExprBox(sub),
+ ExprArray(subs),
+ ExprCall(callee, args),
+ ExprMethodCall(name, ts, args),
+ ExprTup(fields),
+ ExprBinary(op, lhs, rhs),
+ ExprUnary(op, operand),
+ ExprLit(value),
+ ExprCast(expr, t),
+ ExprType(expr, t),
+ ExprIf(cond, then, els),
+ ExprWhile(cond, body, label),
+ ExprLoop(body, label, loop_src),
+ ExprMatch(matchee, arms, match_src),
+ ExprClosure(capture_clause, decl, body_id, span),
+ ExprBlock(blk),
+ ExprAssign(lhs, rhs),
+ ExprAssignOp(op, lhs, rhs),
+ ExprField(owner, field_name),
+ ExprTupField(owner, idx),
+ ExprIndex(lhs, rhs),
+ ExprPath(path),
+ ExprAddrOf(mutability, sub),
+ ExprBreak(destination, sub),
+ ExprAgain(destination),
+ ExprRet(val),
+ ExprInlineAsm(asm, inputs, outputs),
+ ExprStruct(path, fields, base),
+ ExprRepeat(val, times)
+});
+
+impl_stable_hash_for!(enum hir::LoopSource {
+ Loop,
+ WhileLet,
+ ForLoop
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::MatchSource {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ use hir::MatchSource;
+
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ MatchSource::Normal |
+ MatchSource::WhileLetDesugar |
+ MatchSource::ForLoopDesugar |
+ MatchSource::TryDesugar => {
+ // No fields to hash.
+ }
+ MatchSource::IfLetDesugar { contains_else_clause } => {
+ contains_else_clause.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(enum hir::CaptureClause {
+ CaptureByValue,
+ CaptureByRef
+});
+
+impl_stable_hash_for_spanned!(usize);
+
+impl_stable_hash_for!(struct hir::Destination {
+ ident,
+ target_id
+});
+
+impl_stable_hash_for_spanned!(ast::Ident);
+
+impl_stable_hash_for!(enum hir::LoopIdResult {
+ Ok(node_id),
+ Err(loop_id_error)
+});
+
+impl_stable_hash_for!(enum hir::LoopIdError {
+ OutsideLoopScope,
+ UnlabeledCfInWhileCondition,
+ UnresolvedLabel
+});
+
+impl_stable_hash_for!(enum hir::ScopeTarget {
+ Block(node_id),
+ Loop(loop_id_result)
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::Ident {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let ast::Ident {
+ ref name,
+ ctxt: _ // Ignore this
+ } = *self;
+
+ name.hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::TraitItem {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let hir::TraitItem {
+ id,
+ name,
+ ref attrs,
+ ref node,
+ span
+ } = *self;
+
+ hcx.hash_hir_item_like(attrs, |hcx| {
+ id.hash_stable(hcx, hasher);
+ name.hash_stable(hcx, hasher);
+ attrs.hash_stable(hcx, hasher);
+ node.hash_stable(hcx, hasher);
+ span.hash_stable(hcx, hasher);
+ });
+ }
+}
+
+impl_stable_hash_for!(enum hir::TraitMethod {
+ Required(name),
+ Provided(body)
+});
+
+impl_stable_hash_for!(enum hir::TraitItemKind {
+ Const(t, body),
+ Method(sig, method),
+ Type(bounds, rhs)
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::ImplItem {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let hir::ImplItem {
+ id,
+ name,
+ ref vis,
+ defaultness,
+ ref attrs,
+ ref node,
+ span
+ } = *self;
+
+ hcx.hash_hir_item_like(attrs, |hcx| {
+ id.hash_stable(hcx, hasher);
+ name.hash_stable(hcx, hasher);
+ vis.hash_stable(hcx, hasher);
+ defaultness.hash_stable(hcx, hasher);
+ attrs.hash_stable(hcx, hasher);
+ node.hash_stable(hcx, hasher);
+ span.hash_stable(hcx, hasher);
+ });
+ }
+}
+
+impl_stable_hash_for!(enum hir::ImplItemKind {
+ Const(t, body),
+ Method(sig, body),
+ Type(t)
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Visibility {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ hir::Visibility::Public |
+ hir::Visibility::Crate |
+ hir::Visibility::Inherited => {
+ // No fields to hash.
+ }
+ hir::Visibility::Restricted { ref path, id } => {
+ hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashTraitsInScope, |hcx| {
+ id.hash_stable(hcx, hasher);
+ });
+ path.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Defaultness {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ hir::Defaultness::Final => {
+ // No fields to hash.
+ }
+ hir::Defaultness::Default { has_value } => {
+ has_value.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(enum hir::ImplPolarity {
+ Positive,
+ Negative
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Mod {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let hir::Mod {
+ inner,
+ // We are not hashing the IDs of the items contained in the module.
+ // This is harmless and matches the current behavior but it's not
+ // actually correct. See issue #40876.
+ item_ids: _,
+ } = *self;
+
+ inner.hash_stable(hcx, hasher);
+ }
+}
+
+impl_stable_hash_for!(struct hir::ForeignMod {
+ abi,
+ items
+});
+
+impl_stable_hash_for!(struct hir::EnumDef {
+ variants
+});
+
+impl_stable_hash_for!(struct hir::Variant_ {
+ name,
+ attrs,
+ data,
+ disr_expr
+});
+
+impl_stable_hash_for_spanned!(hir::Variant_);
+
+impl_stable_hash_for!(enum hir::UseKind {
+ Single,
+ Glob,
+ ListStem
+});
+
+impl_stable_hash_for!(struct hir::StructField {
+ span,
+ name,
+ vis,
+ id,
+ ty,
+ attrs
+});
+
+impl_stable_hash_for!(enum hir::VariantData {
+ Struct(fields, id),
+ Tuple(fields, id),
+ Unit(id)
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::Item {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let node_id_hashing_mode = match self.node {
+ hir::ItemExternCrate(..) |
+ hir::ItemStatic(..) |
+ hir::ItemConst(..) |
+ hir::ItemFn(..) |
+ hir::ItemMod(..) |
+ hir::ItemForeignMod(..) |
+ hir::ItemTy(..) |
+ hir::ItemEnum(..) |
+ hir::ItemStruct(..) |
+ hir::ItemUnion(..) |
+ hir::ItemTrait(..) |
+ hir::ItemDefaultImpl(..) |
+ hir::ItemImpl(..) => {
+ NodeIdHashingMode::Ignore
+ }
+ hir::ItemUse(..) => {
+ NodeIdHashingMode::HashTraitsInScope
+ }
+ };
+
+ let hir::Item {
+ name,
+ ref attrs,
+ id,
+ ref node,
+ ref vis,
+ span
+ } = *self;
+
+ hcx.hash_hir_item_like(attrs, |hcx| {
+ hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
+ id.hash_stable(hcx, hasher);
+ });
+ name.hash_stable(hcx, hasher);
+ attrs.hash_stable(hcx, hasher);
+ node.hash_stable(hcx, hasher);
+ vis.hash_stable(hcx, hasher);
+ span.hash_stable(hcx, hasher);
+ });
+ }
+}
+
+impl_stable_hash_for!(enum hir::Item_ {
+ ItemExternCrate(name),
+ ItemUse(path, use_kind),
+ ItemStatic(ty, mutability, body_id),
+ ItemConst(ty, body_id),
+ ItemFn(fn_decl, unsafety, constness, abi, generics, body_id),
+ ItemMod(module),
+ ItemForeignMod(foreign_mod),
+ ItemTy(ty, generics),
+ ItemEnum(enum_def, generics),
+ ItemStruct(variant_data, generics),
+ ItemUnion(variant_data, generics),
+ ItemTrait(unsafety, generics, bounds, item_refs),
+ ItemDefaultImpl(unsafety, trait_ref),
+ ItemImpl(unsafety, impl_polarity, generics, trait_ref, ty, impl_item_refs)
+});
+
+impl_stable_hash_for!(struct hir::TraitItemRef {
+ id,
+ name,
+ kind,
+ span,
+ defaultness
+});
+
+impl_stable_hash_for!(struct hir::ImplItemRef {
+ id,
+ name,
+ kind,
+ span,
+ vis,
+ defaultness
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::AssociatedItemKind {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ hir::AssociatedItemKind::Const |
+ hir::AssociatedItemKind::Type => {
+ // No fields to hash.
+ }
+ hir::AssociatedItemKind::Method { has_self } => {
+ has_self.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(struct hir::ForeignItem {
+ name,
+ attrs,
+ node,
+ id,
+ span,
+ vis
+});
+
+impl_stable_hash_for!(enum hir::ForeignItem_ {
+ ForeignItemFn(fn_decl, arg_names, generics),
+ ForeignItemStatic(ty, is_mutbl)
+});
+
+impl_stable_hash_for!(enum hir::Stmt_ {
+ StmtDecl(decl, id),
+ StmtExpr(expr, id),
+ StmtSemi(expr, id)
+});
+
+impl_stable_hash_for!(struct hir::Arg {
+ pat,
+ id
+});
+
+impl_stable_hash_for!(struct hir::Body {
+ arguments,
+ value
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::BodyId {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ if hcx.hash_bodies() {
+ hcx.tcx().hir.body(*self).hash_stable(hcx, hasher);
+ }
+ }
+}
+
+impl_stable_hash_for!(struct hir::InlineAsmOutput {
+ constraint,
+ is_rw,
+ is_indirect
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::InlineAsm {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let hir::InlineAsm {
+ asm,
+ asm_str_style,
+ ref outputs,
+ ref inputs,
+ ref clobbers,
+ volatile,
+ alignstack,
+ dialect,
+ ctxt: _, // This is used for error reporting
+ } = *self;
+
+ asm.hash_stable(hcx, hasher);
+ asm_str_style.hash_stable(hcx, hasher);
+ outputs.hash_stable(hcx, hasher);
+ inputs.hash_stable(hcx, hasher);
+ clobbers.hash_stable(hcx, hasher);
+ volatile.hash_stable(hcx, hasher);
+ alignstack.hash_stable(hcx, hasher);
+ dialect.hash_stable(hcx, hasher);
+ }
+}
+
+impl_stable_hash_for!(enum hir::def::CtorKind {
+ Fn,
+ Const,
+ Fictive
+});
+
+impl_stable_hash_for!(enum hir::def::Def {
+ Mod(def_id),
+ Struct(def_id),
+ Union(def_id),
+ Enum(def_id),
+ Variant(def_id),
+ Trait(def_id),
+ TyAlias(def_id),
+ AssociatedTy(def_id),
+ PrimTy(prim_ty),
+ TyParam(def_id),
+ SelfTy(trait_def_id, impl_def_id),
+ Fn(def_id),
+ Const(def_id),
+ Static(def_id, is_mutbl),
+ StructCtor(def_id, ctor_kind),
+ VariantCtor(def_id, ctor_kind),
+ Method(def_id),
+ AssociatedConst(def_id),
+ Local(def_id),
+ Upvar(def_id, index, expr_id),
+ Label(node_id),
+ Macro(def_id, macro_kind),
+ Err
+});
+
+impl_stable_hash_for!(enum hir::Mutability {
+ MutMutable,
+ MutImmutable
+});
+
+
+impl_stable_hash_for!(enum hir::Unsafety {
+ Unsafe,
+ Normal
+});
+
+
+impl_stable_hash_for!(enum hir::Constness {
+ Const,
+ NotConst
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::def_id::DefIndex {
+
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ DefId::local(*self).hash_stable(hcx, hasher);
+ }
+}
+
+impl_stable_hash_for!(struct hir::def::Export {
+ name,
+ def,
+ span
+});
--- /dev/null
+// Copyright 2017 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.
+
+//! This module contains `HashStable` implementations for various MIR data
+//! types in no particular order.
+
+use ich::StableHashingContext;
+use mir;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+ StableHasherResult};
+use std::mem;
+
+
+impl_stable_hash_for!(struct mir::SourceInfo { span, scope });
+impl_stable_hash_for!(enum mir::Mutability { Mut, Not });
+impl_stable_hash_for!(enum mir::BorrowKind { Shared, Unique, Mut });
+impl_stable_hash_for!(enum mir::LocalKind { Var, Temp, Arg, ReturnPointer });
+impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { mutability, ty, name, source_info });
+impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
+impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup });
+impl_stable_hash_for!(struct mir::Terminator<'tcx> { source_info, kind });
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Local {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ use rustc_data_structures::indexed_vec::Idx;
+ self.index().hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::BasicBlock {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ use rustc_data_structures::indexed_vec::Idx;
+ self.index().hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Field {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ use rustc_data_structures::indexed_vec::Idx;
+ self.index().hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::VisibilityScope {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ use rustc_data_structures::indexed_vec::Idx;
+ self.index().hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Promoted {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ use rustc_data_structures::indexed_vec::Idx;
+ self.index().hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::TerminatorKind<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+
+ match *self {
+ mir::TerminatorKind::Goto { ref target } => {
+ target.hash_stable(hcx, hasher);
+ }
+ mir::TerminatorKind::SwitchInt { ref discr,
+ switch_ty,
+ ref values,
+ ref targets } => {
+ discr.hash_stable(hcx, hasher);
+ switch_ty.hash_stable(hcx, hasher);
+ values.hash_stable(hcx, hasher);
+ targets.hash_stable(hcx, hasher);
+ }
+ mir::TerminatorKind::Resume |
+ mir::TerminatorKind::Return |
+ mir::TerminatorKind::Unreachable => {}
+ mir::TerminatorKind::Drop { ref location, target, unwind } => {
+ location.hash_stable(hcx, hasher);
+ target.hash_stable(hcx, hasher);
+ unwind.hash_stable(hcx, hasher);
+ }
+ mir::TerminatorKind::DropAndReplace { ref location,
+ ref value,
+ target,
+ unwind, } => {
+ location.hash_stable(hcx, hasher);
+ value.hash_stable(hcx, hasher);
+ target.hash_stable(hcx, hasher);
+ unwind.hash_stable(hcx, hasher);
+ }
+ mir::TerminatorKind::Call { ref func,
+ ref args,
+ ref destination,
+ cleanup } => {
+ func.hash_stable(hcx, hasher);
+ args.hash_stable(hcx, hasher);
+ destination.hash_stable(hcx, hasher);
+ cleanup.hash_stable(hcx, hasher);
+ }
+ mir::TerminatorKind::Assert { ref cond,
+ expected,
+ ref msg,
+ target,
+ cleanup } => {
+ cond.hash_stable(hcx, hasher);
+ expected.hash_stable(hcx, hasher);
+ msg.hash_stable(hcx, hasher);
+ target.hash_stable(hcx, hasher);
+ cleanup.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::AssertMessage<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+
+ match *self {
+ mir::AssertMessage::BoundsCheck { ref len, ref index } => {
+ len.hash_stable(hcx, hasher);
+ index.hash_stable(hcx, hasher);
+ }
+ mir::AssertMessage::Math(ref const_math_err) => {
+ const_math_err.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind });
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::StatementKind<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+
+ match *self {
+ mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
+ lvalue.hash_stable(hcx, hasher);
+ rvalue.hash_stable(hcx, hasher);
+ }
+ mir::StatementKind::SetDiscriminant { ref lvalue, variant_index } => {
+ lvalue.hash_stable(hcx, hasher);
+ variant_index.hash_stable(hcx, hasher);
+ }
+ mir::StatementKind::StorageLive(ref lvalue) |
+ mir::StatementKind::StorageDead(ref lvalue) => {
+ lvalue.hash_stable(hcx, hasher);
+ }
+ mir::StatementKind::Nop => {}
+ mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
+ asm.hash_stable(hcx, hasher);
+ outputs.hash_stable(hcx, hasher);
+ inputs.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Lvalue<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ mir::Lvalue::Local(ref local) => {
+ local.hash_stable(hcx, hasher);
+ }
+ mir::Lvalue::Static(ref statik) => {
+ statik.hash_stable(hcx, hasher);
+ }
+ mir::Lvalue::Projection(ref lvalue_projection) => {
+ lvalue_projection.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx, B, V> HashStable<StableHashingContext<'a, 'tcx>> for mir::Projection<'tcx, B, V>
+ where B: HashStable<StableHashingContext<'a, 'tcx>>,
+ V: HashStable<StableHashingContext<'a, 'tcx>>
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let mir::Projection {
+ ref base,
+ ref elem,
+ } = *self;
+
+ base.hash_stable(hcx, hasher);
+ elem.hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx, V> HashStable<StableHashingContext<'a, 'tcx>> for mir::ProjectionElem<'tcx, V>
+ where V: HashStable<StableHashingContext<'a, 'tcx>>
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ mir::ProjectionElem::Deref => {}
+ mir::ProjectionElem::Field(field, ty) => {
+ field.hash_stable(hcx, hasher);
+ ty.hash_stable(hcx, hasher);
+ }
+ mir::ProjectionElem::Index(ref value) => {
+ value.hash_stable(hcx, hasher);
+ }
+ mir::ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
+ offset.hash_stable(hcx, hasher);
+ min_length.hash_stable(hcx, hasher);
+ from_end.hash_stable(hcx, hasher);
+ }
+ mir::ProjectionElem::Subslice { from, to } => {
+ from.hash_stable(hcx, hasher);
+ to.hash_stable(hcx, hasher);
+ }
+ mir::ProjectionElem::Downcast(adt_def, variant) => {
+ adt_def.hash_stable(hcx, hasher);
+ variant.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(struct mir::VisibilityScopeData { span, parent_scope });
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Operand<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+
+ match *self {
+ mir::Operand::Consume(ref lvalue) => {
+ lvalue.hash_stable(hcx, hasher);
+ }
+ mir::Operand::Constant(ref constant) => {
+ constant.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Rvalue<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+
+ match *self {
+ mir::Rvalue::Use(ref operand) => {
+ operand.hash_stable(hcx, hasher);
+ }
+ mir::Rvalue::Repeat(ref operand, ref val) => {
+ operand.hash_stable(hcx, hasher);
+ val.hash_stable(hcx, hasher);
+ }
+ mir::Rvalue::Ref(region, borrow_kind, ref lvalue) => {
+ region.hash_stable(hcx, hasher);
+ borrow_kind.hash_stable(hcx, hasher);
+ lvalue.hash_stable(hcx, hasher);
+ }
+ mir::Rvalue::Len(ref lvalue) => {
+ lvalue.hash_stable(hcx, hasher);
+ }
+ mir::Rvalue::Cast(cast_kind, ref operand, ty) => {
+ cast_kind.hash_stable(hcx, hasher);
+ operand.hash_stable(hcx, hasher);
+ ty.hash_stable(hcx, hasher);
+ }
+ mir::Rvalue::BinaryOp(op, ref operand1, ref operand2) |
+ mir::Rvalue::CheckedBinaryOp(op, ref operand1, ref operand2) => {
+ op.hash_stable(hcx, hasher);
+ operand1.hash_stable(hcx, hasher);
+ operand2.hash_stable(hcx, hasher);
+ }
+ mir::Rvalue::UnaryOp(op, ref operand) => {
+ op.hash_stable(hcx, hasher);
+ operand.hash_stable(hcx, hasher);
+ }
+ mir::Rvalue::Discriminant(ref lvalue) => {
+ lvalue.hash_stable(hcx, hasher);
+ }
+ mir::Rvalue::Box(ty) => {
+ ty.hash_stable(hcx, hasher);
+ }
+ mir::Rvalue::Aggregate(ref kind, ref operands) => {
+ kind.hash_stable(hcx, hasher);
+ operands.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(enum mir::CastKind {
+ Misc,
+ ReifyFnPointer,
+ ClosureFnPointer,
+ UnsafeFnPointer,
+ Unsize
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::AggregateKind<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ mir::AggregateKind::Tuple => {}
+ mir::AggregateKind::Array(t) => {
+ t.hash_stable(hcx, hasher);
+ }
+ mir::AggregateKind::Adt(adt_def, idx, substs, active_field) => {
+ adt_def.hash_stable(hcx, hasher);
+ idx.hash_stable(hcx, hasher);
+ substs.hash_stable(hcx, hasher);
+ active_field.hash_stable(hcx, hasher);
+ }
+ mir::AggregateKind::Closure(def_id, ref substs) => {
+ def_id.hash_stable(hcx, hasher);
+ substs.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(enum mir::BinOp {
+ Add,
+ Sub,
+ Mul,
+ Div,
+ Rem,
+ BitXor,
+ BitAnd,
+ BitOr,
+ Shl,
+ Shr,
+ Eq,
+ Lt,
+ Le,
+ Ne,
+ Ge,
+ Gt
+});
+
+impl_stable_hash_for!(enum mir::UnOp {
+ Not,
+ Neg
+});
+
+
+impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal });
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Literal<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ mir::Literal::Item { def_id, substs } => {
+ def_id.hash_stable(hcx, hasher);
+ substs.hash_stable(hcx, hasher);
+ }
+ mir::Literal::Value { ref value } => {
+ value.hash_stable(hcx, hasher);
+ }
+ mir::Literal::Promoted { index } => {
+ index.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(struct mir::Location { block, statement_index });
--- /dev/null
+// Copyright 2017 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.
+
+//! This module contains `HashStable` implementations for various data types
+//! from libsyntax in no particular order.
+
+use ich::StableHashingContext;
+
+use std::hash as std_hash;
+use std::mem;
+
+use syntax::ast;
+use syntax::parse::token;
+use syntax::tokenstream;
+use syntax_pos::Span;
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+ StableHasherResult};
+use rustc_data_structures::accumulate_vec::AccumulateVec;
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::syntax::symbol::InternedString {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let s: &str = &**self;
+ s.hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::Name {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ self.as_str().hash_stable(hcx, hasher);
+ }
+}
+
+impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
+ Att,
+ Intel
+});
+
+impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
+ Bang,
+ Attr,
+ Derive
+});
+
+
+impl_stable_hash_for!(enum ::syntax::abi::Abi {
+ Cdecl,
+ Stdcall,
+ Fastcall,
+ Vectorcall,
+ Aapcs,
+ Win64,
+ SysV64,
+ PtxKernel,
+ Msp430Interrupt,
+ X86Interrupt,
+ Rust,
+ C,
+ System,
+ RustIntrinsic,
+ RustCall,
+ PlatformIntrinsic,
+ Unadjusted
+});
+
+impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
+impl_stable_hash_for!(struct ::syntax::attr::Stability { level, feature, rustc_depr });
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::syntax::attr::StabilityLevel {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
+ reason.hash_stable(hcx, hasher);
+ issue.hash_stable(hcx, hasher);
+ }
+ ::syntax::attr::StabilityLevel::Stable { ref since } => {
+ since.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
+
+
+impl_stable_hash_for!(enum ::syntax::attr::IntType {
+ SignedInt(int_ty),
+ UnsignedInt(uint_ty)
+});
+
+impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
+ Signed(int_ty),
+ Unsigned(int_ty),
+ Unsuffixed
+});
+
+impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
+impl_stable_hash_for!(enum ::syntax::ast::LitKind {
+ Str(value, style),
+ ByteStr(value),
+ Byte(value),
+ Char(value),
+ Int(value, lit_int_type),
+ Float(value, float_ty),
+ FloatUnsuffixed(value),
+ Bool(value)
+});
+
+impl_stable_hash_for!(enum ::syntax::ast::IntTy { Is, I8, I16, I32, I64, I128 });
+impl_stable_hash_for!(enum ::syntax::ast::UintTy { Us, U8, U16, U32, U64, U128 });
+impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
+impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
+impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
+impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
+impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, name });
+impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
+impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for [ast::Attribute] {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ // Some attributes are always ignored during hashing.
+ let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
+ .iter()
+ .filter(|attr| {
+ !attr.is_sugared_doc &&
+ attr.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true)
+ })
+ .collect();
+
+ filtered.len().hash_stable(hcx, hasher);
+ for attr in filtered {
+ attr.hash_stable(hcx, hasher);
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::Attribute {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ // Make sure that these have been filtered out.
+ debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true));
+ debug_assert!(!self.is_sugared_doc);
+
+ let ast::Attribute {
+ id: _,
+ style,
+ ref path,
+ ref tokens,
+ is_sugared_doc: _,
+ span,
+ } = *self;
+
+ style.hash_stable(hcx, hasher);
+ path.segments.len().hash_stable(hcx, hasher);
+ for segment in &path.segments {
+ segment.identifier.name.hash_stable(hcx, hasher);
+ }
+ for tt in tokens.trees() {
+ tt.hash_stable(hcx, hasher);
+ }
+ span.hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for tokenstream::TokenTree {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ tokenstream::TokenTree::Token(span, ref token) => {
+ span.hash_stable(hcx, hasher);
+ hash_token(token, hcx, hasher, span);
+ }
+ tokenstream::TokenTree::Delimited(span, ref delimited) => {
+ span.hash_stable(hcx, hasher);
+ std_hash::Hash::hash(&delimited.delim, hasher);
+ for sub_tt in delimited.stream().trees() {
+ sub_tt.hash_stable(hcx, hasher);
+ }
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for tokenstream::TokenStream {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ for sub_tt in self.trees() {
+ sub_tt.hash_stable(hcx, hasher);
+ }
+ }
+}
+
+fn hash_token<'a, 'tcx, W: StableHasherResult>(token: &token::Token,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>,
+ error_reporting_span: Span) {
+ mem::discriminant(token).hash_stable(hcx, hasher);
+ match *token {
+ token::Token::Eq |
+ token::Token::Lt |
+ token::Token::Le |
+ token::Token::EqEq |
+ token::Token::Ne |
+ token::Token::Ge |
+ token::Token::Gt |
+ token::Token::AndAnd |
+ token::Token::OrOr |
+ token::Token::Not |
+ token::Token::Tilde |
+ token::Token::At |
+ token::Token::Dot |
+ token::Token::DotDot |
+ token::Token::DotDotDot |
+ token::Token::Comma |
+ token::Token::Semi |
+ token::Token::Colon |
+ token::Token::ModSep |
+ token::Token::RArrow |
+ token::Token::LArrow |
+ token::Token::FatArrow |
+ token::Token::Pound |
+ token::Token::Dollar |
+ token::Token::Question |
+ token::Token::Underscore |
+ token::Token::Whitespace |
+ token::Token::Comment |
+ token::Token::Eof => {}
+
+ token::Token::BinOp(bin_op_token) |
+ token::Token::BinOpEq(bin_op_token) => {
+ std_hash::Hash::hash(&bin_op_token, hasher);
+ }
+
+ token::Token::OpenDelim(delim_token) |
+ token::Token::CloseDelim(delim_token) => {
+ std_hash::Hash::hash(&delim_token, hasher);
+ }
+ token::Token::Literal(ref lit, ref opt_name) => {
+ mem::discriminant(lit).hash_stable(hcx, hasher);
+ match *lit {
+ token::Lit::Byte(val) |
+ token::Lit::Char(val) |
+ token::Lit::Integer(val) |
+ token::Lit::Float(val) |
+ token::Lit::Str_(val) |
+ token::Lit::ByteStr(val) => val.hash_stable(hcx, hasher),
+ token::Lit::StrRaw(val, n) |
+ token::Lit::ByteStrRaw(val, n) => {
+ val.hash_stable(hcx, hasher);
+ n.hash_stable(hcx, hasher);
+ }
+ };
+ opt_name.hash_stable(hcx, hasher);
+ }
+
+ token::Token::Ident(ident) |
+ token::Token::Lifetime(ident) |
+ token::Token::SubstNt(ident) => ident.name.hash_stable(hcx, hasher),
+
+ token::Token::Interpolated(ref non_terminal) => {
+ // FIXME(mw): This could be implemented properly. It's just a
+ // lot of work, since we would need to hash the AST
+ // in a stable way, in addition to the HIR.
+ // Since this is hardly used anywhere, just emit a
+ // warning for now.
+ if hcx.tcx().sess.opts.debugging_opts.incremental.is_some() {
+ let msg = format!("Quasi-quoting might make incremental \
+ compilation very inefficient: {:?}",
+ non_terminal);
+ hcx.tcx().sess.span_warn(error_reporting_span, &msg[..]);
+ }
+
+ std_hash::Hash::hash(non_terminal, hasher);
+ }
+
+ token::Token::DocComment(val) |
+ token::Token::Shebang(val) => val.hash_stable(hcx, hasher),
+ }
+}
--- /dev/null
+// Copyright 2017 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.
+
+//! This module contains `HashStable` implementations for various data types
+//! from rustc::ty in no particular order.
+
+use ich::StableHashingContext;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+ StableHasherResult};
+use std::hash as std_hash;
+use std::mem;
+use ty;
+
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Ty<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let type_hash = hcx.tcx().type_id_hash(*self);
+ type_hash.hash_stable(hcx, hasher);
+ }
+}
+
+impl_stable_hash_for!(struct ty::ItemSubsts<'tcx> { substs });
+
+impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for ty::Slice<T>
+ where T: HashStable<StableHashingContext<'a, 'tcx>> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ (&**self).hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::subst::Kind<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ self.as_type().hash_stable(hcx, hasher);
+ self.as_region().hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Region {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ ty::ReErased |
+ ty::ReStatic |
+ ty::ReEmpty => {
+ // No variant fields to hash for these ...
+ }
+ ty::ReLateBound(db, ty::BrAnon(i)) => {
+ db.depth.hash_stable(hcx, hasher);
+ i.hash_stable(hcx, hasher);
+ }
+ ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
+ index.hash_stable(hcx, hasher);
+ name.hash_stable(hcx, hasher);
+ }
+ ty::ReLateBound(..) |
+ ty::ReFree(..) |
+ ty::ReScope(..) |
+ ty::ReVar(..) |
+ ty::ReSkolemized(..) => {
+ bug!("TypeIdHasher: unexpected region {:?}", *self)
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::adjustment::AutoBorrow<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ ty::adjustment::AutoBorrow::Ref(ref region, mutability) => {
+ region.hash_stable(hcx, hasher);
+ mutability.hash_stable(hcx, hasher);
+ }
+ ty::adjustment::AutoBorrow::RawPtr(mutability) => {
+ mutability.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::adjustment::Adjust<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ ty::adjustment::Adjust::NeverToAny |
+ ty::adjustment::Adjust::ReifyFnPointer |
+ ty::adjustment::Adjust::UnsafeFnPointer |
+ ty::adjustment::Adjust::ClosureFnPointer |
+ ty::adjustment::Adjust::MutToConstPointer => {}
+ ty::adjustment::Adjust::DerefRef { autoderefs, ref autoref, unsize } => {
+ autoderefs.hash_stable(hcx, hasher);
+ autoref.hash_stable(hcx, hasher);
+ unsize.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(struct ty::adjustment::Adjustment<'tcx> { kind, target });
+impl_stable_hash_for!(struct ty::MethodCall { expr_id, autoderef });
+impl_stable_hash_for!(struct ty::MethodCallee<'tcx> { def_id, ty, substs });
+impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
+impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region });
+
+impl_stable_hash_for!(enum ty::BorrowKind {
+ ImmBorrow,
+ UniqueImmBorrow,
+ MutBorrow
+});
+
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::UpvarCapture<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ ty::UpvarCapture::ByValue => {}
+ ty::UpvarCapture::ByRef(ref up_var_borrow) => {
+ up_var_borrow.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(struct ty::FnSig<'tcx> {
+ inputs_and_output,
+ variadic,
+ unsafety,
+ abi
+});
+
+impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for ty::Binder<T>
+ where T: HashStable<StableHashingContext<'a, 'tcx>> + ty::fold::TypeFoldable<'tcx>
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ hcx.tcx().anonymize_late_bound_regions(self).0.hash_stable(hcx, hasher);
+ }
+}
+
+impl_stable_hash_for!(enum ty::ClosureKind { Fn, FnMut, FnOnce });
+
+impl_stable_hash_for!(enum ty::Visibility {
+ Public,
+ Restricted(def_id),
+ Invisible
+});
+
+impl_stable_hash_for!(struct ty::TraitRef<'tcx> { def_id, substs });
+impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref });
+impl_stable_hash_for!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 });
+
+impl<'a, 'tcx, A, B> HashStable<StableHashingContext<'a, 'tcx>> for ty::OutlivesPredicate<A, B>
+ where A: HashStable<StableHashingContext<'a, 'tcx>>,
+ B: HashStable<StableHashingContext<'a, 'tcx>>,
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let ty::OutlivesPredicate(ref a, ref b) = *self;
+ a.hash_stable(hcx, hasher);
+ b.hash_stable(hcx, hasher);
+ }
+}
+
+impl_stable_hash_for!(struct ty::ProjectionPredicate<'tcx> { projection_ty, ty });
+impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { trait_ref, item_name });
+
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Predicate<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ ty::Predicate::Trait(ref pred) => {
+ pred.hash_stable(hcx, hasher);
+ }
+ ty::Predicate::Equate(ref pred) => {
+ pred.hash_stable(hcx, hasher);
+ }
+ ty::Predicate::RegionOutlives(ref pred) => {
+ pred.hash_stable(hcx, hasher);
+ }
+ ty::Predicate::TypeOutlives(ref pred) => {
+ pred.hash_stable(hcx, hasher);
+ }
+ ty::Predicate::Projection(ref pred) => {
+ pred.hash_stable(hcx, hasher);
+ }
+ ty::Predicate::WellFormed(ty) => {
+ ty.hash_stable(hcx, hasher);
+ }
+ ty::Predicate::ObjectSafe(def_id) => {
+ def_id.hash_stable(hcx, hasher);
+ }
+ ty::Predicate::ClosureKind(def_id, closure_kind) => {
+ def_id.hash_stable(hcx, hasher);
+ closure_kind.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::AdtFlags {
+ fn hash_stable<W: StableHasherResult>(&self,
+ _: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ std_hash::Hash::hash(self, hasher);
+ }
+}
+
+impl_stable_hash_for!(struct ty::VariantDef {
+ did,
+ name,
+ discr,
+ fields,
+ ctor_kind
+});
+
+impl_stable_hash_for!(enum ty::VariantDiscr {
+ Explicit(def_id),
+ Relative(distance)
+});
+
+impl_stable_hash_for!(struct ty::FieldDef {
+ did,
+ name,
+ vis
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>>
+for ::middle::const_val::ConstVal<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ use middle::const_val::ConstVal;
+
+ mem::discriminant(self).hash_stable(hcx, hasher);
+
+ match *self {
+ ConstVal::Float(ref value) => {
+ value.hash_stable(hcx, hasher);
+ }
+ ConstVal::Integral(ref value) => {
+ value.hash_stable(hcx, hasher);
+ }
+ ConstVal::Str(ref value) => {
+ value.hash_stable(hcx, hasher);
+ }
+ ConstVal::ByteStr(ref value) => {
+ value.hash_stable(hcx, hasher);
+ }
+ ConstVal::Bool(value) => {
+ value.hash_stable(hcx, hasher);
+ }
+ ConstVal::Function(def_id, substs) => {
+ def_id.hash_stable(hcx, hasher);
+ substs.hash_stable(hcx, hasher);
+ }
+ ConstVal::Struct(ref _name_value_map) => {
+ // BTreeMap<ast::Name, ConstVal<'tcx>>),
+ panic!("Ordering still unstable")
+ }
+ ConstVal::Tuple(ref value) => {
+ value.hash_stable(hcx, hasher);
+ }
+ ConstVal::Array(ref value) => {
+ value.hash_stable(hcx, hasher);
+ }
+ ConstVal::Repeat(ref value, times) => {
+ value.hash_stable(hcx, hasher);
+ times.hash_stable(hcx, hasher);
+ }
+ ConstVal::Char(value) => {
+ value.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
+
+
+impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
+ parent,
+ predicates
+});
+
+impl_stable_hash_for!(enum ty::Variance {
+ Covariant,
+ Invariant,
+ Contravariant,
+ Bivariant
+});
+
+impl_stable_hash_for!(enum ty::adjustment::CustomCoerceUnsized {
+ Struct(index)
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Generics {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let ty::Generics {
+ parent,
+ parent_regions,
+ parent_types,
+ ref regions,
+ ref types,
+
+ // Reverse map to each `TypeParameterDef`'s `index` field, from
+ // `def_id.index` (`def_id.krate` is the same as the item's).
+ type_param_to_index: _, // Don't hash this
+ has_self,
+ } = *self;
+
+ parent.hash_stable(hcx, hasher);
+ parent_regions.hash_stable(hcx, hasher);
+ parent_types.hash_stable(hcx, hasher);
+ regions.hash_stable(hcx, hasher);
+ types.hash_stable(hcx, hasher);
+ has_self.hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionParameterDef {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let ty::RegionParameterDef {
+ name,
+ def_id,
+ index,
+ issue_32330: _,
+ pure_wrt_drop
+ } = *self;
+
+ name.hash_stable(hcx, hasher);
+ def_id.hash_stable(hcx, hasher);
+ index.hash_stable(hcx, hasher);
+ pure_wrt_drop.hash_stable(hcx, hasher);
+ }
+}
+
+impl_stable_hash_for!(struct ty::TypeParameterDef {
+ name,
+ def_id,
+ index,
+ has_default,
+ object_lifetime_default,
+ pure_wrt_drop
+});
+
+
+impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>>
+for ::middle::resolve_lifetime::Set1<T>
+ where T: HashStable<StableHashingContext<'a, 'tcx>>
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ use middle::resolve_lifetime::Set1;
+
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match *self {
+ Set1::Empty |
+ Set1::Many => {
+ // Nothing to do.
+ }
+ Set1::One(ref value) => {
+ value.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+impl_stable_hash_for!(enum ::middle::resolve_lifetime::Region {
+ Static,
+ EarlyBound(index, decl),
+ LateBound(db_index, decl),
+ LateBoundAnon(db_index, anon_index),
+ Free(call_site_scope_data, decl)
+});
+
+impl_stable_hash_for!(struct ::middle::region::CallSiteScopeData {
+ fn_id,
+ body_id
+});
+
+impl_stable_hash_for!(struct ty::DebruijnIndex {
+ depth
+});
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+//! ICH - Incremental Compilation Hash
+
pub use self::fingerprint::Fingerprint;
pub use self::def_path_hash::DefPathHashes;
pub use self::caching_codemap_view::CachingCodemapView;
+pub use self::hcx::{StableHashingContext, NodeIdHashingMode};
mod fingerprint;
mod def_path_hash;
mod caching_codemap_view;
+mod hcx;
+
+mod impls_const_math;
+mod impls_hir;
+mod impls_mir;
+mod impls_ty;
+mod impls_syntax;
pub const ATTR_DIRTY: &'static str = "rustc_dirty";
pub const ATTR_CLEAN: &'static str = "rustc_clean";
pub const ATTR_CLEAN_METADATA: &'static str = "rustc_metadata_clean";
pub const ATTR_IF_THIS_CHANGED: &'static str = "rustc_if_this_changed";
pub const ATTR_THEN_THIS_WOULD_NEED: &'static str = "rustc_then_this_would_need";
+pub const ATTR_PARTITION_REUSED: &'static str = "rustc_partition_reused";
+pub const ATTR_PARTITION_TRANSLATED: &'static str = "rustc_partition_translated";
+
+
+pub const DEP_GRAPH_ASSERT_ATTRS: &'static [&'static str] = &[
+ ATTR_IF_THIS_CHANGED,
+ ATTR_THEN_THIS_WOULD_NEED,
+ ATTR_DIRTY,
+ ATTR_CLEAN,
+ ATTR_DIRTY_METADATA,
+ ATTR_CLEAN_METADATA,
+ ATTR_PARTITION_REUSED,
+ ATTR_PARTITION_TRANSLATED,
+];
pub const IGNORED_ATTRIBUTES: &'static [&'static str] = &[
"cfg",
ATTR_DIRTY,
ATTR_CLEAN,
ATTR_DIRTY_METADATA,
- ATTR_CLEAN_METADATA
+ ATTR_CLEAN_METADATA,
+ ATTR_PARTITION_REUSED,
+ ATTR_PARTITION_TRANSLATED,
];
#![feature(specialization)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
+#![feature(discriminant_value)]
extern crate arena;
extern crate core;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-tidy-linelength
+
macro_rules! enum_from_u32 {
($(#[$attr:meta])* pub enum $name:ident {
$($variant:ident = $e:expr,)*
$crate::session::span_bug_fmt(file!(), line!(), $span, format_args!($($message)*))
})
}
+
+#[macro_export]
+macro_rules! __impl_stable_hash_field {
+ (DECL IGNORED) => (_);
+ (DECL $name:ident) => (ref $name);
+ (USE IGNORED $ctx:expr, $hasher:expr) => ({});
+ (USE $name:ident, $ctx:expr, $hasher:expr) => ($name.hash_stable($ctx, $hasher));
+}
+
+#[macro_export]
+macro_rules! impl_stable_hash_for {
+ (enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* }) => {
+ impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $enum_name {
+ #[inline]
+ fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
+ __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>,
+ __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
+ use $enum_name::*;
+ ::std::mem::discriminant(self).hash_stable(__ctx, __hasher);
+
+ match *self {
+ $(
+ $variant $( ( $( __impl_stable_hash_field!(DECL $arg) ),* ) )* => {
+ $($( __impl_stable_hash_field!(USE $arg, __ctx, __hasher) );*)*
+ }
+ )*
+ }
+ }
+ }
+ };
+ (struct $struct_name:path { $($field:ident),* }) => {
+ impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $struct_name {
+ #[inline]
+ fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
+ __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>,
+ __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
+ let $struct_name {
+ $(ref $field),*
+ } = *self;
+
+ $( $field.hash_stable(__ctx, __hasher));*
+ }
+ }
+ };
+ (tuple_struct $struct_name:path { $($field:ident),* }) => {
+ impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $struct_name {
+ #[inline]
+ fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
+ __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>,
+ __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
+ let $struct_name (
+ $(ref $field),*
+ ) = *self;
+
+ $( $field.hash_stable(__ctx, __hasher));*
+ }
+ }
+ };
+}
+
+#[macro_export]
+macro_rules! impl_stable_hash_for_spanned {
+ ($T:path) => (
+
+ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::syntax::codemap::Spanned<$T>
+ {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ self.node.hash_stable(hcx, hasher);
+ self.span.hash_stable(hcx, hasher);
+ }
+ }
+ );
+}
+
use std::cell::{Ref, RefCell};
use rustc_data_structures::indexed_vec::IndexVec;
-
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
+ StableHasherResult};
+use ich::StableHashingContext;
use mir::{Mir, BasicBlock};
use rustc_serialize as serialize;
}
}
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for Cache {
+ fn hash_stable<W: StableHasherResult>(&self,
+ _: &mut StableHashingContext<'a, 'tcx>,
+ _: &mut StableHasher<W>) {
+ // do nothing
+ }
+}
impl Cache {
pub fn new() -> Self {
}
}
+impl_stable_hash_for!(struct Mir<'tcx> {
+ basic_blocks,
+ visibility_scopes,
+ promoted,
+ return_ty,
+ local_decls,
+ arg_count,
+ upvar_decls,
+ spread_arg,
+ span,
+ cache
+});
+
impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
type Output = BasicBlockData<'tcx>;
pub ty: Ty<'tcx>,
}
+impl_stable_hash_for!(struct Static<'tcx> {
+ def_id,
+ ty
+});
+
/// The `Projection` data structure defines things of the form `B.x`
/// or `*B` or `B[index]`. Note that it is parameterized because it is
/// shared between `Constant` and `Lvalue`. See the aliases
/// Alignment of a type in bytes, both ABI-mandated and preferred.
/// Since alignments are always powers of 2, we can pack both in one byte,
-/// giving each a nibble (4 bits) for a maximum alignment of 2^15 = 32768.
+/// giving each a nibble (4 bits) for a maximum alignment of 2<sup>15</sup> = 32768.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Align {
raw: u8
use hir::{map as hir_map, FreevarMap, TraitMap};
use hir::def::{Def, CtorKind, ExportMap};
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use ich::StableHashingContext;
use middle::const_val::ConstVal;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::privacy::AccessLevels;
use rustc_const_math::ConstInt;
use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
+use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
+ HashStable};
use hir;
use hir::itemlikevisit::ItemLikeVisitor;
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for AdtDef {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let ty::AdtDef {
+ did,
+ ref variants,
+ ref flags,
+ ref repr,
+ } = *self;
+
+ did.hash_stable(hcx, hasher);
+ variants.hash_stable(hcx, hasher);
+ flags.hash_stable(hcx, hasher);
+ repr.hash_stable(hcx, hasher);
+ }
+}
+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AdtKind { Struct, Union, Enum }
pub int: Option<attr::IntType>,
}
+impl_stable_hash_for!(struct ReprOptions {
+ c,
+ packed,
+ simd,
+ int
+});
+
impl ReprOptions {
pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions {
let mut ret = ReprOptions::default();
_ => span_bug!(e.span, "typeck error"),
})
}
+ (Char(a), Char(b)) => {
+ Bool(match op.node {
+ hir::BiEq => a == b,
+ hir::BiNe => a != b,
+ hir::BiLt => a < b,
+ hir::BiLe => a <= b,
+ hir::BiGe => a >= b,
+ hir::BiGt => a > b,
+ _ => span_bug!(e.span, "typeck error"),
+ })
+ }
_ => signal!(e, MiscBinaryOp),
}
#![feature(unsize)]
#![feature(i128_type)]
#![feature(conservative_impl_trait)]
+#![feature(discriminant_value)]
+#![feature(specialization)]
#![cfg_attr(unix, feature(libc))]
#![cfg_attr(test, feature(test))]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::hash::Hasher;
+use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::mem;
use blake2b::Blake2bHasher;
self.write_ileb128(i as i64);
}
}
+
+
+/// Something that implements `HashStable<CTX>` can be hashed in a way that is
+/// stable across multiple compiliation sessions.
+pub trait HashStable<CTX> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut CTX,
+ hasher: &mut StableHasher<W>);
+}
+
+// Implement HashStable by just calling `Hash::hash()`. This works fine for
+// self-contained values that don't depend on the hashing context `CTX`.
+macro_rules! impl_stable_hash_via_hash {
+ ($t:ty) => (
+ impl<CTX> HashStable<CTX> for $t {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ _: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ ::std::hash::Hash::hash(self, hasher);
+ }
+ }
+ );
+}
+
+impl_stable_hash_via_hash!(i8);
+impl_stable_hash_via_hash!(i16);
+impl_stable_hash_via_hash!(i32);
+impl_stable_hash_via_hash!(i64);
+impl_stable_hash_via_hash!(isize);
+
+impl_stable_hash_via_hash!(u8);
+impl_stable_hash_via_hash!(u16);
+impl_stable_hash_via_hash!(u32);
+impl_stable_hash_via_hash!(u64);
+impl_stable_hash_via_hash!(usize);
+
+impl_stable_hash_via_hash!(u128);
+impl_stable_hash_via_hash!(i128);
+
+impl_stable_hash_via_hash!(char);
+impl_stable_hash_via_hash!(());
+
+impl<CTX> HashStable<CTX> for f32 {
+ fn hash_stable<W: StableHasherResult>(&self,
+ ctx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ let val: u32 = unsafe {
+ ::std::mem::transmute(*self)
+ };
+ val.hash_stable(ctx, hasher);
+ }
+}
+
+impl<CTX> HashStable<CTX> for f64 {
+ fn hash_stable<W: StableHasherResult>(&self,
+ ctx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ let val: u64 = unsafe {
+ ::std::mem::transmute(*self)
+ };
+ val.hash_stable(ctx, hasher);
+ }
+}
+
+impl<T1: HashStable<CTX>, T2: HashStable<CTX>, CTX> HashStable<CTX> for (T1, T2) {
+ fn hash_stable<W: StableHasherResult>(&self,
+ ctx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ self.0.hash_stable(ctx, hasher);
+ self.1.hash_stable(ctx, hasher);
+ }
+}
+
+impl<T: HashStable<CTX>, CTX> HashStable<CTX> for [T] {
+ default fn hash_stable<W: StableHasherResult>(&self,
+ ctx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ self.len().hash_stable(ctx, hasher);
+ for item in self {
+ item.hash_stable(ctx, hasher);
+ }
+ }
+}
+
+impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Vec<T> {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ ctx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ (&self[..]).hash_stable(ctx, hasher);
+ }
+}
+
+impl<CTX> HashStable<CTX> for str {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ _: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ self.len().hash(hasher);
+ self.as_bytes().hash(hasher);
+ }
+}
+
+impl<CTX> HashStable<CTX> for bool {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ ctx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ (if *self { 1u8 } else { 0u8 }).hash_stable(ctx, hasher);
+ }
+}
+
+
+impl<T, CTX> HashStable<CTX> for Option<T>
+ where T: HashStable<CTX>
+{
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ ctx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ if let Some(ref value) = *self {
+ 1u8.hash_stable(ctx, hasher);
+ value.hash_stable(ctx, hasher);
+ } else {
+ 0u8.hash_stable(ctx, hasher);
+ }
+ }
+}
+
+impl<'a, T, CTX> HashStable<CTX> for &'a T
+ where T: HashStable<CTX>
+{
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ ctx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ (**self).hash_stable(ctx, hasher);
+ }
+}
+
+impl<T, CTX> HashStable<CTX> for ::std::mem::Discriminant<T> {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ _: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ ::std::hash::Hash::hash(self, hasher);
+ }
+}
+
+impl<K, V, CTX> HashStable<CTX> for ::std::collections::BTreeMap<K, V>
+ where K: Ord + HashStable<CTX>,
+ V: HashStable<CTX>,
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ ctx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ self.len().hash_stable(ctx, hasher);
+ for (k, v) in self {
+ k.hash_stable(ctx, hasher);
+ v.hash_stable(ctx, hasher);
+ }
+ }
+}
+
+impl<T, CTX> HashStable<CTX> for ::std::collections::BTreeSet<T>
+ where T: Ord + HashStable<CTX>,
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ ctx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ self.len().hash_stable(ctx, hasher);
+ for v in self {
+ v.hash_stable(ctx, hasher);
+ }
+ }
+}
+
+impl<I: ::indexed_vec::Idx, T, CTX> HashStable<CTX> for ::indexed_vec::IndexVec<I, T>
+ where T: HashStable<CTX>,
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ ctx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ self.len().hash_stable(ctx, hasher);
+ for v in &self.raw {
+ v.hash_stable(ctx, hasher);
+ }
+ }
+}
.values()
.filter(|a| a.is_none())
.count();
- let ofile = if unnamed_output_types > 1 &&
- sess.opts.output_types.contains_key(&OutputType::Exe) {
- sess.warn("ignoring specified output filename for 'link' output because multiple \
- outputs were requested");
+ let ofile = if unnamed_output_types > 1 {
+ sess.warn("due to multiple output types requested, the explicitly specified \
+ output file name will be adapted for each output type");
None
} else {
Some(out_file.clone())
//! at the end of compilation would be different from those computed
//! at the beginning.
-use syntax::ast;
use std::cell::RefCell;
use std::hash::Hash;
use rustc::dep_graph::DepNode;
use rustc::hir;
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
-use rustc::hir::intravisit as visit;
-use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
-use rustc::ich::{Fingerprint, DefPathHashes, CachingCodemapView};
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::ich::{Fingerprint, StableHashingContext};
use rustc::ty::TyCtxt;
-use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
use rustc_data_structures::fx::FxHashMap;
use rustc::util::common::record_time;
-use rustc::session::config::DebugInfoLevel::NoDebugInfo;
-
-use self::svh_visitor::StrictVersionHashVisitor;
-
-mod svh_visitor;
pub type IchHasher = StableHasher<Fingerprint>;
}
}
-
-pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> IncrementalHashesMap {
- let _ignore = tcx.dep_graph.in_ignore();
- let krate = tcx.hir.krate();
- let hash_spans = tcx.sess.opts.debuginfo != NoDebugInfo;
- let mut visitor = HashItemsVisitor {
- tcx: tcx,
- hashes: IncrementalHashesMap::new(),
- def_path_hashes: DefPathHashes::new(tcx),
- codemap: CachingCodemapView::new(tcx),
- hash_spans: hash_spans,
- };
- record_time(&tcx.sess.perf_stats.incr_comp_hashes_time, || {
- visitor.calculate_def_id(DefId::local(CRATE_DEF_INDEX), |v| {
- v.hash_crate_root_module(krate);
- });
- krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
-
- for macro_def in krate.exported_macros.iter() {
- visitor.calculate_node_id(macro_def.id,
- |v| v.visit_macro_def(macro_def));
- }
- });
-
- tcx.sess.perf_stats.incr_comp_hashes_count.set(visitor.hashes.len() as u64);
-
- record_time(&tcx.sess.perf_stats.svh_time, || visitor.compute_crate_hash());
- visitor.hashes
-}
-
-struct HashItemsVisitor<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- def_path_hashes: DefPathHashes<'a, 'tcx>,
- codemap: CachingCodemapView<'tcx>,
+struct ComputeItemHashesVisitor<'a, 'tcx: 'a> {
+ hcx: StableHashingContext<'a, 'tcx>,
hashes: IncrementalHashesMap,
- hash_spans: bool,
}
-impl<'a, 'tcx> HashItemsVisitor<'a, 'tcx> {
- fn calculate_node_id<W>(&mut self, id: ast::NodeId, walk_op: W)
- where W: for<'v> FnMut(&mut StrictVersionHashVisitor<'v, 'a, 'tcx>)
- {
- let def_id = self.tcx.hir.local_def_id(id);
- self.calculate_def_id(def_id, walk_op)
- }
-
- fn calculate_def_id<W>(&mut self, def_id: DefId, mut walk_op: W)
- where W: for<'v> FnMut(&mut StrictVersionHashVisitor<'v, 'a, 'tcx>)
+impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
+ fn compute_and_store_ich_for_item_like<T>(&mut self,
+ dep_node: DepNode<DefId>,
+ hash_bodies: bool,
+ item_like: T)
+ where T: HashStable<StableHashingContext<'a, 'tcx>>
{
- assert!(def_id.is_local());
- debug!("HashItemsVisitor::calculate(def_id={:?})", def_id);
- self.calculate_def_hash(DepNode::Hir(def_id), false, &mut walk_op);
- self.calculate_def_hash(DepNode::HirBody(def_id), true, &mut walk_op);
- }
+ let mut hasher = IchHasher::new();
+ self.hcx.while_hashing_hir_bodies(hash_bodies, |hcx| {
+ item_like.hash_stable(hcx, &mut hasher);
+ });
- fn calculate_def_hash<W>(&mut self,
- dep_node: DepNode<DefId>,
- hash_bodies: bool,
- walk_op: &mut W)
- where W: for<'v> FnMut(&mut StrictVersionHashVisitor<'v, 'a, 'tcx>)
- {
- let mut state = IchHasher::new();
- walk_op(&mut StrictVersionHashVisitor::new(&mut state,
- self.tcx,
- &mut self.def_path_hashes,
- &mut self.codemap,
- self.hash_spans,
- hash_bodies));
- let bytes_hashed = state.bytes_hashed();
- let item_hash = state.finish();
+ let bytes_hashed = hasher.bytes_hashed();
+ let item_hash = hasher.finish();
debug!("calculate_def_hash: dep_node={:?} hash={:?}", dep_node, item_hash);
self.hashes.insert(dep_node, item_hash);
- let bytes_hashed = self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
+ let tcx = self.hcx.tcx();
+ let bytes_hashed =
+ tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
bytes_hashed;
- self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
+ tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
}
fn compute_crate_hash(&mut self) {
- let krate = self.tcx.hir.krate();
+ let tcx = self.hcx.tcx();
+ let krate = tcx.hir.krate();
let mut crate_state = IchHasher::new();
- let crate_disambiguator = self.tcx.sess.local_crate_disambiguator();
+ let crate_disambiguator = tcx.sess.local_crate_disambiguator();
"crate_disambiguator".hash(&mut crate_state);
crate_disambiguator.as_str().len().hash(&mut crate_state);
crate_disambiguator.as_str().hash(&mut crate_state);
// add each item (in some deterministic order) to the overall
// crate hash.
{
- let def_path_hashes = &mut self.def_path_hashes;
+ let hcx = &mut self.hcx;
let mut item_hashes: Vec<_> =
self.hashes.iter()
.map(|(item_dep_node, &item_hash)| {
// DepNode<u64> where the u64 is the
// hash of the def-id's def-path:
let item_dep_node =
- item_dep_node.map_def(|&did| Some(def_path_hashes.hash(did)))
+ item_dep_node.map_def(|&did| Some(hcx.def_path_hash(did)))
.unwrap();
(item_dep_node, item_hash)
})
item_hashes.hash(&mut crate_state);
}
- {
- let mut visitor = StrictVersionHashVisitor::new(&mut crate_state,
- self.tcx,
- &mut self.def_path_hashes,
- &mut self.codemap,
- self.hash_spans,
- false);
- visitor.hash_attributes(&krate.attrs);
- }
+ krate.attrs.hash_stable(&mut self.hcx, &mut crate_state);
let crate_hash = crate_state.finish();
self.hashes.insert(DepNode::Krate, crate_hash);
debug!("calculate_crate_hash: crate_hash={:?}", crate_hash);
}
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for HashItemsVisitor<'a, 'tcx> {
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
- NestedVisitorMap::None
+ fn hash_crate_root_module(&mut self, krate: &'tcx hir::Crate) {
+ let hir::Crate {
+ ref module,
+ // Crate attributes are not copied over to the root `Mod`, so hash
+ // them explicitly here.
+ ref attrs,
+ span,
+
+ // These fields are handled separately:
+ exported_macros: _,
+ items: _,
+ trait_items: _,
+ impl_items: _,
+ bodies: _,
+ trait_impls: _,
+ trait_default_impl: _,
+ body_ids: _,
+ } = *krate;
+
+ let def_id = DefId::local(CRATE_DEF_INDEX);
+ self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id),
+ false,
+ (module, (span, attrs)));
+ self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id),
+ true,
+ (module, (span, attrs)));
}
+}
+impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
- self.calculate_node_id(item.id, |v| v.visit_item(item));
- visit::walk_item(self, item);
+ let def_id = self.hcx.tcx().hir.local_def_id(item.id);
+ self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item);
+ self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item);
}
- fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
- self.calculate_node_id(trait_item.id, |v| v.visit_trait_item(trait_item));
- visit::walk_trait_item(self, trait_item);
+ fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
+ let def_id = self.hcx.tcx().hir.local_def_id(item.id);
+ self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item);
+ self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item);
}
- fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
- self.calculate_node_id(impl_item.id, |v| v.visit_impl_item(impl_item));
- visit::walk_impl_item(self, impl_item);
+ fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
+ let def_id = self.hcx.tcx().hir.local_def_id(item.id);
+ self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item);
+ self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item);
}
}
+
+pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
+ -> IncrementalHashesMap {
+ let _ignore = tcx.dep_graph.in_ignore();
+ let krate = tcx.hir.krate();
+
+ let mut visitor = ComputeItemHashesVisitor {
+ hcx: StableHashingContext::new(tcx),
+ hashes: IncrementalHashesMap::new(),
+ };
+
+ record_time(&tcx.sess.perf_stats.incr_comp_hashes_time, || {
+ visitor.hash_crate_root_module(krate);
+ krate.visit_all_item_likes(&mut visitor);
+
+ for macro_def in krate.exported_macros.iter() {
+ let def_id = tcx.hir.local_def_id(macro_def.id);
+ visitor.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, macro_def);
+ visitor.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, macro_def);
+ }
+ });
+
+ tcx.sess.perf_stats.incr_comp_hashes_count.set(visitor.hashes.len() as u64);
+
+ record_time(&tcx.sess.perf_stats.svh_time, || visitor.compute_crate_hash());
+ visitor.hashes
+}
+++ /dev/null
-// Copyright 2012-2014 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.
-
-use self::SawExprComponent::*;
-use self::SawAbiComponent::*;
-use self::SawItemComponent::*;
-use self::SawPatComponent::*;
-use self::SawTyComponent::*;
-use self::SawTraitOrImplItemComponent::*;
-use syntax::abi::Abi;
-use syntax::ast::{self, Name, NodeId};
-use syntax::attr;
-use syntax::ext::hygiene::SyntaxContext;
-use syntax::parse::token;
-use syntax::symbol::InternedString;
-use syntax_pos::{Span, BytePos};
-use syntax::tokenstream;
-use rustc::hir;
-use rustc::hir::*;
-use rustc::hir::def::Def;
-use rustc::hir::def_id::DefId;
-use rustc::hir::intravisit::{self as visit, Visitor};
-use rustc::ich::{DefPathHashes, CachingCodemapView, IGNORED_ATTRIBUTES};
-use rustc::ty::TyCtxt;
-use std::hash::{Hash, Hasher};
-
-use super::IchHasher;
-
-pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> {
- pub tcx: TyCtxt<'hash, 'tcx, 'tcx>,
- pub st: &'a mut IchHasher,
- // collect a deterministic hash of def-ids that we have seen
- def_path_hashes: &'a mut DefPathHashes<'hash, 'tcx>,
- hash_spans: bool,
- codemap: &'a mut CachingCodemapView<'tcx>,
- overflow_checks_enabled: bool,
- hash_bodies: bool,
-}
-
-impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
- pub fn new(st: &'a mut IchHasher,
- tcx: TyCtxt<'hash, 'tcx, 'tcx>,
- def_path_hashes: &'a mut DefPathHashes<'hash, 'tcx>,
- codemap: &'a mut CachingCodemapView<'tcx>,
- hash_spans: bool,
- hash_bodies: bool)
- -> Self {
- let check_overflow = tcx.sess.overflow_checks();
-
- StrictVersionHashVisitor {
- st: st,
- tcx: tcx,
- def_path_hashes: def_path_hashes,
- hash_spans: hash_spans,
- codemap: codemap,
- overflow_checks_enabled: check_overflow,
- hash_bodies: hash_bodies,
- }
- }
-
- fn compute_def_id_hash(&mut self, def_id: DefId) -> u64 {
- self.def_path_hashes.hash(def_id)
- }
-
- // Hash a span in a stable way. We can't directly hash the span's BytePos
- // fields (that would be similar to hashing pointers, since those are just
- // offsets into the CodeMap). Instead, we hash the (file name, line, column)
- // triple, which stays the same even if the containing FileMap has moved
- // within the CodeMap.
- // Also note that we are hashing byte offsets for the column, not unicode
- // codepoint offsets. For the purpose of the hash that's sufficient.
- // Also, hashing filenames is expensive so we avoid doing it twice when the
- // span starts and ends in the same file, which is almost always the case.
- fn hash_span(&mut self, span: Span) {
- debug!("hash_span: st={:?}", self.st);
-
- // If this is not an empty or invalid span, we want to hash the last
- // position that belongs to it, as opposed to hashing the first
- // position past it.
- let span_hi = if span.hi > span.lo {
- // We might end up in the middle of a multibyte character here,
- // but that's OK, since we are not trying to decode anything at
- // this position.
- span.hi - BytePos(1)
- } else {
- span.hi
- };
-
- let expn_kind = if span.ctxt == SyntaxContext::empty() {
- SawSpanExpnKind::NoExpansion
- } else {
- SawSpanExpnKind::SomeExpansion
- };
-
- let loc1 = self.codemap.byte_pos_to_line_and_col(span.lo);
- let loc1 = loc1.as_ref()
- .map(|&(ref fm, line, col)| (&fm.name[..], line, col))
- .unwrap_or(("???", 0, BytePos(0)));
-
- let loc2 = self.codemap.byte_pos_to_line_and_col(span_hi);
- let loc2 = loc2.as_ref()
- .map(|&(ref fm, line, col)| (&fm.name[..], line, col))
- .unwrap_or(("???", 0, BytePos(0)));
-
- let saw = if loc1.0 == loc2.0 {
- SawSpan(loc1.0,
- loc1.1, loc1.2,
- loc2.1, loc2.2,
- expn_kind)
- } else {
- SawSpanTwoFiles(loc1.0, loc1.1, loc1.2,
- loc2.0, loc2.1, loc2.2,
- expn_kind)
- };
- saw.hash(self.st);
-
- if expn_kind == SawSpanExpnKind::SomeExpansion {
- self.hash_span(span.source_callsite());
- }
- }
-
- fn hash_discriminant<T>(&mut self, v: &T) {
- unsafe {
- let disr = ::std::intrinsics::discriminant_value(v);
- debug!("hash_discriminant: disr={}, st={:?}", disr, self.st);
- disr.hash(self.st);
- }
- }
-}
-
-// To off-load the bulk of the hash-computation on #[derive(Hash)],
-// we define a set of enums corresponding to the content that our
-// crate visitor will encounter as it traverses the ast.
-//
-// The important invariant is that all of the Saw*Component enums
-// do not carry any Spans, Names, or Idents.
-//
-// Not carrying any Names/Idents is the important fix for problem
-// noted on PR #13948: using the ident.name as the basis for a
-// hash leads to unstable SVH, because ident.name is just an index
-// into intern table (i.e. essentially a random address), not
-// computed from the name content.
-//
-// With the below enums, the SVH computation is not sensitive to
-// artifacts of how rustc was invoked nor of how the source code
-// was laid out. (Or at least it is *less* sensitive.)
-
-// This enum represents the different potential bits of code the
-// visitor could encounter that could affect the ABI for the crate,
-// and assigns each a distinct tag to feed into the hash computation.
-#[derive(Hash)]
-enum SawAbiComponent<'a> {
-
- // FIXME (#14132): should we include (some function of)
- // ident.ctxt as well?
- SawIdent(InternedString),
- SawStructDef(InternedString),
-
- SawLifetime,
- SawLifetimeDef(usize),
-
- SawMod,
- SawForeignItem(SawForeignItemComponent),
- SawItem(SawItemComponent),
- SawTy(SawTyComponent),
- SawFnDecl(bool),
- SawGenerics,
- SawTraitItem(SawTraitOrImplItemComponent),
- SawImplItem(SawTraitOrImplItemComponent),
- SawStructField,
- SawVariant(bool),
- SawQPath,
- SawPathSegment,
- SawPathParameters,
- SawBlock,
- SawPat(SawPatComponent),
- SawLocal,
- SawArm,
- SawExpr(SawExprComponent<'a>),
- SawStmt,
- SawVis,
- SawAssociatedItemKind(hir::AssociatedItemKind),
- SawDefaultness(hir::Defaultness),
- SawWherePredicate,
- SawTyParamBound,
- SawPolyTraitRef,
- SawAssocTypeBinding,
- SawAttribute(ast::AttrStyle),
- SawMacroDef,
- SawSpan(&'a str,
- usize, BytePos,
- usize, BytePos,
- SawSpanExpnKind),
- SawSpanTwoFiles(&'a str, usize, BytePos,
- &'a str, usize, BytePos,
- SawSpanExpnKind),
-}
-
-/// SawExprComponent carries all of the information that we want
-/// to include in the hash that *won't* be covered by the
-/// subsequent recursive traversal of the expression's
-/// substructure by the visitor.
-///
-/// We know every Expr_ variant is covered by a variant because
-/// `fn saw_expr` maps each to some case below. Ensuring that
-/// each variant carries an appropriate payload has to be verified
-/// by hand.
-///
-/// (However, getting that *exactly* right is not so important
-/// because the SVH is just a developer convenience; there is no
-/// guarantee of collision-freedom, hash collisions are just
-/// (hopefully) unlikely.)
-///
-/// The xxxComponent enums and saw_xxx functions for Item, Pat,
-/// Ty, TraitItem and ImplItem follow the same methodology.
-#[derive(Hash)]
-enum SawExprComponent<'a> {
-
- SawExprLoop(Option<InternedString>),
- SawExprField(InternedString),
- SawExprTupField(usize),
- SawExprBreak(Option<InternedString>),
- SawExprAgain(Option<InternedString>),
-
- SawExprBox,
- SawExprArray,
- SawExprCall,
- SawExprMethodCall,
- SawExprTup,
- SawExprBinary(hir::BinOp_),
- SawExprUnary(hir::UnOp),
- SawExprLit(ast::LitKind),
- SawExprLitStr(InternedString, ast::StrStyle),
- SawExprLitFloat(InternedString, Option<ast::FloatTy>),
- SawExprCast,
- SawExprType,
- SawExprIf,
- SawExprWhile,
- SawExprMatch,
- SawExprClosure(CaptureClause),
- SawExprBlock,
- SawExprAssign,
- SawExprAssignOp(hir::BinOp_),
- SawExprIndex,
- SawExprPath,
- SawExprAddrOf(hir::Mutability),
- SawExprRet,
- SawExprInlineAsm(StableInlineAsm<'a>),
- SawExprStruct,
- SawExprRepeat,
-}
-
-// The boolean returned indicates whether the span of this expression is always
-// significant, regardless of debuginfo.
-fn saw_expr<'a>(node: &'a Expr_,
- overflow_checks_enabled: bool)
- -> (SawExprComponent<'a>, bool) {
- let binop_can_panic_at_runtime = |binop| {
- match binop {
- BiAdd |
- BiSub |
- BiMul => overflow_checks_enabled,
-
- BiDiv |
- BiRem => true,
-
- BiAnd |
- BiOr |
- BiBitXor |
- BiBitAnd |
- BiBitOr |
- BiShl |
- BiShr |
- BiEq |
- BiLt |
- BiLe |
- BiNe |
- BiGe |
- BiGt => false
- }
- };
-
- let unop_can_panic_at_runtime = |unop| {
- match unop {
- UnDeref |
- UnNot => false,
- UnNeg => overflow_checks_enabled,
- }
- };
-
- match *node {
- ExprBox(..) => (SawExprBox, false),
- ExprArray(..) => (SawExprArray, false),
- ExprCall(..) => (SawExprCall, false),
- ExprMethodCall(..) => (SawExprMethodCall, false),
- ExprTup(..) => (SawExprTup, false),
- ExprBinary(op, ..) => {
- (SawExprBinary(op.node), binop_can_panic_at_runtime(op.node))
- }
- ExprUnary(op, _) => {
- (SawExprUnary(op), unop_can_panic_at_runtime(op))
- }
- ExprLit(ref lit) => (saw_lit(lit), false),
- ExprCast(..) => (SawExprCast, false),
- ExprType(..) => (SawExprType, false),
- ExprIf(..) => (SawExprIf, false),
- ExprWhile(..) => (SawExprWhile, false),
- ExprLoop(_, id, _) => (SawExprLoop(id.map(|id| id.node.as_str())), false),
- ExprMatch(..) => (SawExprMatch, false),
- ExprClosure(cc, _, _, _) => (SawExprClosure(cc), false),
- ExprBlock(..) => (SawExprBlock, false),
- ExprAssign(..) => (SawExprAssign, false),
- ExprAssignOp(op, ..) => {
- (SawExprAssignOp(op.node), binop_can_panic_at_runtime(op.node))
- }
- ExprField(_, name) => (SawExprField(name.node.as_str()), false),
- ExprTupField(_, id) => (SawExprTupField(id.node), false),
- ExprIndex(..) => (SawExprIndex, true),
- ExprPath(_) => (SawExprPath, false),
- ExprAddrOf(m, _) => (SawExprAddrOf(m), false),
- ExprBreak(label, _) => (SawExprBreak(label.ident.map(|i|
- i.node.name.as_str())), false),
- ExprAgain(label) => (SawExprAgain(label.ident.map(|i|
- i.node.name.as_str())), false),
- ExprRet(..) => (SawExprRet, false),
- ExprInlineAsm(ref a,..) => (SawExprInlineAsm(StableInlineAsm(a)), false),
- ExprStruct(..) => (SawExprStruct, false),
- ExprRepeat(..) => (SawExprRepeat, false),
- }
-}
-
-fn saw_lit(lit: &ast::Lit) -> SawExprComponent<'static> {
- match lit.node {
- ast::LitKind::Str(s, style) => SawExprLitStr(s.as_str(), style),
- ast::LitKind::Float(s, ty) => SawExprLitFloat(s.as_str(), Some(ty)),
- ast::LitKind::FloatUnsuffixed(s) => SawExprLitFloat(s.as_str(), None),
- ref node @ _ => SawExprLit(node.clone()),
- }
-}
-
-#[derive(Hash)]
-enum SawItemComponent {
- SawItemExternCrate,
- SawItemUse(UseKind),
- SawItemStatic(Mutability),
- SawItemConst,
- SawItemFn(Unsafety, Constness, Abi),
- SawItemMod,
- SawItemForeignMod(Abi),
- SawItemTy,
- SawItemEnum,
- SawItemStruct,
- SawItemUnion,
- SawItemTrait(Unsafety),
- SawItemDefaultImpl(Unsafety),
- SawItemImpl(Unsafety, ImplPolarity)
-}
-
-fn saw_item(node: &Item_) -> SawItemComponent {
- match *node {
- ItemExternCrate(..) => SawItemExternCrate,
- ItemUse(_, kind) => SawItemUse(kind),
- ItemStatic(_, mutability, _) => SawItemStatic(mutability),
- ItemConst(..) =>SawItemConst,
- ItemFn(_, unsafety, constness, abi, _, _) => SawItemFn(unsafety, constness, abi),
- ItemMod(..) => SawItemMod,
- ItemForeignMod(ref fm) => SawItemForeignMod(fm.abi),
- ItemTy(..) => SawItemTy,
- ItemEnum(..) => SawItemEnum,
- ItemStruct(..) => SawItemStruct,
- ItemUnion(..) => SawItemUnion,
- ItemTrait(unsafety, ..) => SawItemTrait(unsafety),
- ItemDefaultImpl(unsafety, _) => SawItemDefaultImpl(unsafety),
- ItemImpl(unsafety, implpolarity, ..) => SawItemImpl(unsafety, implpolarity)
- }
-}
-
-#[derive(Hash)]
-enum SawForeignItemComponent {
- Static { mutable: bool },
- Fn,
-}
-
-#[derive(Hash)]
-enum SawPatComponent {
- SawPatWild,
- SawPatBinding(BindingMode),
- SawPatStruct,
- SawPatTupleStruct,
- SawPatPath,
- SawPatTuple,
- SawPatBox,
- SawPatRef(Mutability),
- SawPatLit,
- SawPatRange,
- SawPatSlice
-}
-
-fn saw_pat(node: &PatKind) -> SawPatComponent {
- match *node {
- PatKind::Wild => SawPatWild,
- PatKind::Binding(bindingmode, ..) => SawPatBinding(bindingmode),
- PatKind::Struct(..) => SawPatStruct,
- PatKind::TupleStruct(..) => SawPatTupleStruct,
- PatKind::Path(_) => SawPatPath,
- PatKind::Tuple(..) => SawPatTuple,
- PatKind::Box(..) => SawPatBox,
- PatKind::Ref(_, mutability) => SawPatRef(mutability),
- PatKind::Lit(..) => SawPatLit,
- PatKind::Range(..) => SawPatRange,
- PatKind::Slice(..) => SawPatSlice
- }
-}
-
-#[derive(Hash)]
-enum SawTyComponent {
- SawTySlice,
- SawTyArray,
- SawTyPtr(Mutability),
- SawTyRptr(Mutability),
- SawTyBareFn(Unsafety, Abi),
- SawTyNever,
- SawTyTup,
- SawTyPath,
- SawTyObjectSum,
- SawTyImplTrait,
- SawTyTypeof,
- SawTyInfer
-}
-
-fn saw_ty(node: &Ty_) -> SawTyComponent {
- match *node {
- TySlice(..) => SawTySlice,
- TyArray(..) => SawTyArray,
- TyPtr(ref mty) => SawTyPtr(mty.mutbl),
- TyRptr(_, ref mty) => SawTyRptr(mty.mutbl),
- TyBareFn(ref barefnty) => SawTyBareFn(barefnty.unsafety, barefnty.abi),
- TyNever => SawTyNever,
- TyTup(..) => SawTyTup,
- TyPath(_) => SawTyPath,
- TyTraitObject(..) => SawTyObjectSum,
- TyImplTrait(..) => SawTyImplTrait,
- TyTypeof(..) => SawTyTypeof,
- TyInfer => SawTyInfer
- }
-}
-
-#[derive(Hash)]
-enum SawTraitOrImplItemComponent {
- SawTraitOrImplItemConst,
- // The boolean signifies whether a body is present
- SawTraitOrImplItemMethod(Unsafety, Constness, Abi, bool),
- SawTraitOrImplItemType
-}
-
-fn saw_trait_item(ti: &TraitItemKind) -> SawTraitOrImplItemComponent {
- match *ti {
- TraitItemKind::Const(..) => SawTraitOrImplItemConst,
- TraitItemKind::Method(ref sig, TraitMethod::Required(_)) =>
- SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, false),
- TraitItemKind::Method(ref sig, TraitMethod::Provided(_)) =>
- SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, true),
- TraitItemKind::Type(..) => SawTraitOrImplItemType
- }
-}
-
-fn saw_impl_item(ii: &ImplItemKind) -> SawTraitOrImplItemComponent {
- match *ii {
- ImplItemKind::Const(..) => SawTraitOrImplItemConst,
- ImplItemKind::Method(ref sig, _) =>
- SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, true),
- ImplItemKind::Type(..) => SawTraitOrImplItemType
- }
-}
-
-#[derive(Clone, Copy, Hash, Eq, PartialEq)]
-enum SawSpanExpnKind {
- NoExpansion,
- SomeExpansion,
-}
-
-/// A wrapper that provides a stable Hash implementation.
-struct StableInlineAsm<'a>(&'a InlineAsm);
-
-impl<'a> Hash for StableInlineAsm<'a> {
- fn hash<H: Hasher>(&self, state: &mut H) {
- let InlineAsm {
- asm,
- asm_str_style,
- ref outputs,
- ref inputs,
- ref clobbers,
- volatile,
- alignstack,
- dialect,
- ctxt: _, // This is used for error reporting
- } = *self.0;
-
- asm.as_str().hash(state);
- asm_str_style.hash(state);
- outputs.len().hash(state);
- for output in outputs {
- let InlineAsmOutput { constraint, is_rw, is_indirect } = *output;
- constraint.as_str().hash(state);
- is_rw.hash(state);
- is_indirect.hash(state);
- }
- inputs.len().hash(state);
- for input in inputs {
- input.as_str().hash(state);
- }
- clobbers.len().hash(state);
- for clobber in clobbers {
- clobber.as_str().hash(state);
- }
- volatile.hash(state);
- alignstack.hash(state);
- dialect.hash(state);
- }
-}
-
-macro_rules! hash_attrs {
- ($visitor:expr, $attrs:expr) => ({
- let attrs = $attrs;
- if attrs.len() > 0 {
- $visitor.hash_attributes(attrs);
- }
- })
-}
-
-macro_rules! hash_span {
- ($visitor:expr, $span:expr) => ({
- hash_span!($visitor, $span, false)
- });
- ($visitor:expr, $span:expr, $force:expr) => ({
- if $force || $visitor.hash_spans {
- $visitor.hash_span($span);
- }
- });
-}
-
-impl<'a, 'hash, 'tcx> Visitor<'tcx> for StrictVersionHashVisitor<'a, 'hash, 'tcx> {
- fn nested_visit_map<'this>(&'this mut self) -> visit::NestedVisitorMap<'this, 'tcx> {
- if self.hash_bodies {
- visit::NestedVisitorMap::OnlyBodies(&self.tcx.hir)
- } else {
- visit::NestedVisitorMap::None
- }
- }
-
- fn visit_variant_data(&mut self,
- s: &'tcx VariantData,
- name: Name,
- _: &'tcx Generics,
- _: NodeId,
- span: Span) {
- debug!("visit_variant_data: st={:?}", self.st);
- SawStructDef(name.as_str()).hash(self.st);
- hash_span!(self, span);
- visit::walk_struct_def(self, s);
- }
-
- fn visit_variant(&mut self,
- v: &'tcx Variant,
- g: &'tcx Generics,
- item_id: NodeId) {
- debug!("visit_variant: st={:?}", self.st);
- SawVariant(v.node.disr_expr.is_some()).hash(self.st);
- hash_attrs!(self, &v.node.attrs);
- visit::walk_variant(self, v, g, item_id)
- }
-
- fn visit_name(&mut self, span: Span, name: Name) {
- debug!("visit_name: st={:?}", self.st);
- SawIdent(name.as_str()).hash(self.st);
- hash_span!(self, span);
- }
-
- fn visit_lifetime(&mut self, l: &'tcx Lifetime) {
- debug!("visit_lifetime: st={:?}", self.st);
- SawLifetime.hash(self.st);
- visit::walk_lifetime(self, l);
- }
-
- fn visit_lifetime_def(&mut self, l: &'tcx LifetimeDef) {
- debug!("visit_lifetime_def: st={:?}", self.st);
- SawLifetimeDef(l.bounds.len()).hash(self.st);
- visit::walk_lifetime_def(self, l);
- }
-
- fn visit_expr(&mut self, ex: &'tcx Expr) {
- debug!("visit_expr: st={:?}", self.st);
- let (saw_expr, force_span) = saw_expr(&ex.node,
- self.overflow_checks_enabled);
- SawExpr(saw_expr).hash(self.st);
- // No need to explicitly hash the discriminant here, since we are
- // implicitly hashing the discriminant of SawExprComponent.
- hash_span!(self, ex.span, force_span);
- hash_attrs!(self, &ex.attrs);
-
- // Always hash nested constant bodies (e.g. n in `[x; n]`).
- let hash_bodies = self.hash_bodies;
- self.hash_bodies = true;
- visit::walk_expr(self, ex);
- self.hash_bodies = hash_bodies;
- }
-
- fn visit_stmt(&mut self, s: &'tcx Stmt) {
- debug!("visit_stmt: st={:?}", self.st);
-
- // We don't want to modify the hash for decls, because
- // they might be item decls (if they are local decls,
- // we'll hash that fact in visit_local); but we do want to
- // remember if this was a StmtExpr or StmtSemi (the later
- // had an explicit semi-colon; this affects the typing
- // rules).
- match s.node {
- StmtDecl(..) => (),
- StmtExpr(..) => {
- SawStmt.hash(self.st);
- self.hash_discriminant(&s.node);
- hash_span!(self, s.span);
- }
- StmtSemi(..) => {
- SawStmt.hash(self.st);
- self.hash_discriminant(&s.node);
- hash_span!(self, s.span);
- }
- }
-
- visit::walk_stmt(self, s)
- }
-
- fn visit_foreign_item(&mut self, i: &'tcx ForeignItem) {
- debug!("visit_foreign_item: st={:?}", self.st);
-
- match i.node {
- ForeignItemFn(..) => {
- SawForeignItem(SawForeignItemComponent::Fn)
- }
- ForeignItemStatic(_, mutable) => {
- SawForeignItem(SawForeignItemComponent::Static {
- mutable: mutable
- })
- }
- }.hash(self.st);
-
- hash_span!(self, i.span);
- hash_attrs!(self, &i.attrs);
- visit::walk_foreign_item(self, i)
- }
-
- fn visit_item(&mut self, i: &'tcx Item) {
- debug!("visit_item: {:?} st={:?}", i, self.st);
-
- self.maybe_enable_overflow_checks(&i.attrs);
-
- SawItem(saw_item(&i.node)).hash(self.st);
- hash_span!(self, i.span);
- hash_attrs!(self, &i.attrs);
- visit::walk_item(self, i)
- }
-
- fn visit_mod(&mut self, m: &'tcx Mod, span: Span, n: NodeId) {
- debug!("visit_mod: st={:?}", self.st);
- SawMod.hash(self.st);
- hash_span!(self, span);
- visit::walk_mod(self, m, n)
- }
-
- fn visit_ty(&mut self, t: &'tcx Ty) {
- debug!("visit_ty: st={:?}", self.st);
- SawTy(saw_ty(&t.node)).hash(self.st);
- hash_span!(self, t.span);
-
- // Always hash nested constant bodies (e.g. N in `[T; N]`).
- let hash_bodies = self.hash_bodies;
- self.hash_bodies = true;
- visit::walk_ty(self, t);
- self.hash_bodies = hash_bodies;
- }
-
- fn visit_generics(&mut self, g: &'tcx Generics) {
- debug!("visit_generics: st={:?}", self.st);
- SawGenerics.hash(self.st);
- visit::walk_generics(self, g)
- }
-
- fn visit_fn_decl(&mut self, fd: &'tcx FnDecl) {
- debug!("visit_fn_decl: st={:?}", self.st);
- SawFnDecl(fd.variadic).hash(self.st);
- visit::walk_fn_decl(self, fd)
- }
-
- fn visit_trait_item(&mut self, ti: &'tcx TraitItem) {
- debug!("visit_trait_item: st={:?}", self.st);
-
- self.maybe_enable_overflow_checks(&ti.attrs);
-
- SawTraitItem(saw_trait_item(&ti.node)).hash(self.st);
- hash_span!(self, ti.span);
- hash_attrs!(self, &ti.attrs);
- visit::walk_trait_item(self, ti)
- }
-
- fn visit_impl_item(&mut self, ii: &'tcx ImplItem) {
- debug!("visit_impl_item: st={:?}", self.st);
-
- self.maybe_enable_overflow_checks(&ii.attrs);
-
- SawImplItem(saw_impl_item(&ii.node)).hash(self.st);
- hash_span!(self, ii.span);
- hash_attrs!(self, &ii.attrs);
- visit::walk_impl_item(self, ii)
- }
-
- fn visit_struct_field(&mut self, s: &'tcx StructField) {
- debug!("visit_struct_field: st={:?}", self.st);
- SawStructField.hash(self.st);
- hash_span!(self, s.span);
- hash_attrs!(self, &s.attrs);
- visit::walk_struct_field(self, s)
- }
-
- fn visit_qpath(&mut self, qpath: &'tcx QPath, id: NodeId, span: Span) {
- debug!("visit_qpath: st={:?}", self.st);
- SawQPath.hash(self.st);
- self.hash_discriminant(qpath);
- visit::walk_qpath(self, qpath, id, span)
- }
-
- fn visit_path(&mut self, path: &'tcx Path, _: ast::NodeId) {
- debug!("visit_path: st={:?}", self.st);
- hash_span!(self, path.span);
- visit::walk_path(self, path)
- }
-
- fn visit_def_mention(&mut self, def: Def) {
- self.hash_def(def);
- }
-
- fn visit_block(&mut self, b: &'tcx Block) {
- debug!("visit_block: st={:?}", self.st);
- SawBlock.hash(self.st);
- hash_span!(self, b.span);
- visit::walk_block(self, b)
- }
-
- fn visit_pat(&mut self, p: &'tcx Pat) {
- debug!("visit_pat: st={:?}", self.st);
- SawPat(saw_pat(&p.node)).hash(self.st);
- hash_span!(self, p.span);
- visit::walk_pat(self, p)
- }
-
- fn visit_local(&mut self, l: &'tcx Local) {
- debug!("visit_local: st={:?}", self.st);
- SawLocal.hash(self.st);
- hash_attrs!(self, &l.attrs);
- visit::walk_local(self, l)
- // No need to hash span, we are hashing all component spans
- }
-
- fn visit_arm(&mut self, a: &'tcx Arm) {
- debug!("visit_arm: st={:?}", self.st);
- SawArm.hash(self.st);
- hash_attrs!(self, &a.attrs);
- visit::walk_arm(self, a)
- }
-
- fn visit_id(&mut self, id: NodeId) {
- debug!("visit_id: id={} st={:?}", id, self.st);
- self.hash_resolve(id)
- }
-
- fn visit_vis(&mut self, v: &'tcx Visibility) {
- debug!("visit_vis: st={:?}", self.st);
- SawVis.hash(self.st);
- self.hash_discriminant(v);
- visit::walk_vis(self, v)
- }
-
- fn visit_associated_item_kind(&mut self, kind: &'tcx AssociatedItemKind) {
- debug!("visit_associated_item_kind: st={:?}", self.st);
- SawAssociatedItemKind(*kind).hash(self.st);
- visit::walk_associated_item_kind(self, kind);
- }
-
- fn visit_defaultness(&mut self, defaultness: &'tcx Defaultness) {
- debug!("visit_associated_item_kind: st={:?}", self.st);
- SawDefaultness(*defaultness).hash(self.st);
- visit::walk_defaultness(self, defaultness);
- }
-
- fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate) {
- debug!("visit_where_predicate: st={:?}", self.st);
- SawWherePredicate.hash(self.st);
- self.hash_discriminant(predicate);
- // Ignoring span. Any important nested components should be visited.
- visit::walk_where_predicate(self, predicate)
- }
-
- fn visit_ty_param_bound(&mut self, bounds: &'tcx TyParamBound) {
- debug!("visit_ty_param_bound: st={:?}", self.st);
- SawTyParamBound.hash(self.st);
- self.hash_discriminant(bounds);
- // The TraitBoundModifier in TraitTyParamBound will be hash in
- // visit_poly_trait_ref()
- visit::walk_ty_param_bound(self, bounds)
- }
-
- fn visit_poly_trait_ref(&mut self, t: &'tcx PolyTraitRef, m: TraitBoundModifier) {
- debug!("visit_poly_trait_ref: st={:?}", self.st);
- SawPolyTraitRef.hash(self.st);
- m.hash(self.st);
- visit::walk_poly_trait_ref(self, t, m)
- }
-
- fn visit_path_segment(&mut self, path_span: Span, path_segment: &'tcx PathSegment) {
- debug!("visit_path_segment: st={:?}", self.st);
- SawPathSegment.hash(self.st);
- visit::walk_path_segment(self, path_span, path_segment)
- }
-
- fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'tcx PathParameters) {
- debug!("visit_path_parameters: st={:?}", self.st);
- SawPathParameters.hash(self.st);
- self.hash_discriminant(path_parameters);
- visit::walk_path_parameters(self, path_span, path_parameters)
- }
-
- fn visit_assoc_type_binding(&mut self, type_binding: &'tcx TypeBinding) {
- debug!("visit_assoc_type_binding: st={:?}", self.st);
- SawAssocTypeBinding.hash(self.st);
- hash_span!(self, type_binding.span);
- visit::walk_assoc_type_binding(self, type_binding)
- }
-
- fn visit_attribute(&mut self, _: &ast::Attribute) {
- // We explicitly do not use this method, since doing that would
- // implicitly impose an order on the attributes being hashed, while we
- // explicitly don't want their order to matter
- }
-
- fn visit_macro_def(&mut self, macro_def: &'tcx MacroDef) {
- debug!("visit_macro_def: st={:?}", self.st);
- SawMacroDef.hash(self.st);
- hash_attrs!(self, ¯o_def.attrs);
- for tt in macro_def.body.trees() {
- self.hash_token_tree(&tt);
- }
- visit::walk_macro_def(self, macro_def)
- }
-}
-
-#[derive(Hash)]
-pub enum DefHash {
- SawDefId,
- SawLabel,
- SawPrimTy,
- SawSelfTy,
- SawErr,
-}
-
-impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
- fn hash_resolve(&mut self, id: ast::NodeId) {
- // Because whether or not a given id has an entry is dependent
- // solely on expr variant etc, we don't need to hash whether
- // or not an entry was present (we are already hashing what
- // variant it is above when we visit the HIR).
-
- if let Some(traits) = self.tcx.trait_map.get(&id) {
- debug!("hash_resolve: id={:?} traits={:?} st={:?}", id, traits, self.st);
- traits.len().hash(self.st);
-
- // The ordering of the candidates is not fixed. So we hash
- // the def-ids and then sort them and hash the collection.
- let mut candidates: Vec<_> =
- traits.iter()
- .map(|&TraitCandidate { def_id, import_id: _ }| {
- self.compute_def_id_hash(def_id)
- })
- .collect();
- candidates.sort();
- candidates.hash(self.st);
- }
- }
-
- fn hash_def_id(&mut self, def_id: DefId) {
- self.compute_def_id_hash(def_id).hash(self.st);
- }
-
- fn hash_def(&mut self, def: Def) {
- match def {
- // Crucial point: for all of these variants, the variant +
- // add'l data that is added is always the same if the
- // def-id is the same, so it suffices to hash the def-id
- Def::Fn(..) |
- Def::Mod(..) |
- Def::Static(..) |
- Def::Variant(..) |
- Def::VariantCtor(..) |
- Def::Enum(..) |
- Def::TyAlias(..) |
- Def::AssociatedTy(..) |
- Def::TyParam(..) |
- Def::Struct(..) |
- Def::StructCtor(..) |
- Def::Union(..) |
- Def::Trait(..) |
- Def::Method(..) |
- Def::Const(..) |
- Def::AssociatedConst(..) |
- Def::Local(..) |
- Def::Upvar(..) |
- Def::Macro(..) => {
- DefHash::SawDefId.hash(self.st);
- self.hash_def_id(def.def_id());
- }
-
- Def::Label(..) => {
- DefHash::SawLabel.hash(self.st);
- // we don't encode the `id` because it always refers to something
- // within this item, so if it changed, there would have to be other
- // changes too
- }
- Def::PrimTy(ref prim_ty) => {
- DefHash::SawPrimTy.hash(self.st);
- prim_ty.hash(self.st);
- }
- Def::SelfTy(..) => {
- DefHash::SawSelfTy.hash(self.st);
- // the meaning of Self is always the same within a
- // given context, so we don't need to hash the other
- // fields
- }
- Def::Err => {
- DefHash::SawErr.hash(self.st);
- }
- }
- }
-
- pub fn hash_attributes(&mut self, attributes: &[ast::Attribute]) {
- debug!("hash_attributes: st={:?}", self.st);
- let indices = self.indices_sorted_by(attributes, |attr| attr.name());
-
- for i in indices {
- let attr = &attributes[i];
- match attr.name() {
- Some(name) if IGNORED_ATTRIBUTES.contains(&&*name.as_str()) => continue,
- _ => {}
- };
- if !attr.is_sugared_doc {
- SawAttribute(attr.style).hash(self.st);
- for segment in &attr.path.segments {
- SawIdent(segment.identifier.name.as_str()).hash(self.st);
- }
- for tt in attr.tokens.trees() {
- self.hash_token_tree(&tt);
- }
- }
- }
- }
-
- fn indices_sorted_by<T, K, F>(&mut self, items: &[T], get_key: F) -> Vec<usize>
- where K: Ord,
- F: Fn(&T) -> K
- {
- let mut indices = Vec::with_capacity(items.len());
- indices.extend(0 .. items.len());
- indices.sort_by_key(|index| get_key(&items[*index]));
- indices
- }
-
- fn maybe_enable_overflow_checks(&mut self, item_attrs: &[ast::Attribute]) {
- if attr::contains_name(item_attrs, "rustc_inherit_overflow_checks") {
- self.overflow_checks_enabled = true;
- }
- }
-
- fn hash_token_tree(&mut self, tt: &tokenstream::TokenTree) {
- self.hash_discriminant(tt);
- match *tt {
- tokenstream::TokenTree::Token(span, ref token) => {
- hash_span!(self, span);
- self.hash_token(token, span);
- }
- tokenstream::TokenTree::Delimited(span, ref delimited) => {
- hash_span!(self, span);
- delimited.delim.hash(self.st);
- for sub_tt in delimited.stream().trees() {
- self.hash_token_tree(&sub_tt);
- }
- }
- }
- }
-
- fn hash_token(&mut self,
- token: &token::Token,
- error_reporting_span: Span) {
- self.hash_discriminant(token);
- match *token {
- token::Token::Eq |
- token::Token::Lt |
- token::Token::Le |
- token::Token::EqEq |
- token::Token::Ne |
- token::Token::Ge |
- token::Token::Gt |
- token::Token::AndAnd |
- token::Token::OrOr |
- token::Token::Not |
- token::Token::Tilde |
- token::Token::At |
- token::Token::Dot |
- token::Token::DotDot |
- token::Token::DotDotDot |
- token::Token::Comma |
- token::Token::Semi |
- token::Token::Colon |
- token::Token::ModSep |
- token::Token::RArrow |
- token::Token::LArrow |
- token::Token::FatArrow |
- token::Token::Pound |
- token::Token::Dollar |
- token::Token::Question |
- token::Token::Underscore |
- token::Token::Whitespace |
- token::Token::Comment |
- token::Token::Eof => {}
-
- token::Token::BinOp(bin_op_token) |
- token::Token::BinOpEq(bin_op_token) => bin_op_token.hash(self.st),
-
- token::Token::OpenDelim(delim_token) |
- token::Token::CloseDelim(delim_token) => delim_token.hash(self.st),
-
- token::Token::Literal(ref lit, ref opt_name) => {
- self.hash_discriminant(lit);
- match *lit {
- token::Lit::Byte(val) |
- token::Lit::Char(val) |
- token::Lit::Integer(val) |
- token::Lit::Float(val) |
- token::Lit::Str_(val) |
- token::Lit::ByteStr(val) => val.as_str().hash(self.st),
- token::Lit::StrRaw(val, n) |
- token::Lit::ByteStrRaw(val, n) => {
- val.as_str().hash(self.st);
- n.hash(self.st);
- }
- };
- opt_name.map(ast::Name::as_str).hash(self.st);
- }
-
- token::Token::Ident(ident) |
- token::Token::Lifetime(ident) |
- token::Token::SubstNt(ident) => ident.name.as_str().hash(self.st),
-
- token::Token::Interpolated(ref non_terminal) => {
- // FIXME(mw): This could be implemented properly. It's just a
- // lot of work, since we would need to hash the AST
- // in a stable way, in addition to the HIR.
- // Since this is hardly used anywhere, just emit a
- // warning for now.
- if self.tcx.sess.opts.debugging_opts.incremental.is_some() {
- let msg = format!("Quasi-quoting might make incremental \
- compilation very inefficient: {:?}",
- non_terminal);
- self.tcx.sess.span_warn(error_reporting_span, &msg[..]);
- }
-
- non_terminal.hash(self.st);
- }
-
- token::Token::DocComment(val) |
- token::Token::Shebang(val) => val.as_str().hash(self.st),
- }
- }
-
- pub fn hash_crate_root_module(&mut self, krate: &'tcx Crate) {
- let hir::Crate {
- ref module,
- ref attrs,
- span,
-
- // These fields are handled separately:
- exported_macros: _,
- items: _,
- trait_items: _,
- impl_items: _,
- bodies: _,
- trait_impls: _,
- trait_default_impl: _,
- body_ids: _,
- } = *krate;
-
- visit::Visitor::visit_mod(self, module, span, ast::CRATE_NODE_ID);
- // Crate attributes are not copied over to the root `Mod`, so hash them
- // explicitly here.
- hash_attrs!(self, attrs);
- }
-}
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(rand)]
-#![feature(core_intrinsics)]
#![feature(conservative_impl_trait)]
#![cfg_attr(stage0, feature(pub_restricted))]
println!("cargo:rustc-link-lib={}", stdcppname);
}
}
+
+ // LLVM requires symbols from this library, but apparently they're not printeds
+ // during llvm-config?
+ if target.contains("windows") {
+ println!("cargo:rustc-link-lib=ole32");
+ }
}
pub fn LLVMRustUnsetComdat(V: ValueRef);
pub fn LLVMRustSetModulePIELevel(M: ModuleRef);
}
-
-
-// LLVM requires symbols from this library, but apparently they're not printed
-// during llvm-config?
-#[cfg(windows)]
-#[link(name = "ole32")]
-extern "C" {}
&mut self.basic_blocks[blk]
}
+ // llvm.org/PR32488 makes this function use an excess of stack space. Mark
+ // it as #[inline(never)] to keep rustc's stack use in check.
+ #[inline(never)]
pub fn start_new_block(&mut self) -> BasicBlock {
self.basic_blocks.push(BasicBlockData::new(None))
}
let name = unwrap_or!(attrs[i].name(), continue);
if name == "derive" {
- let result = attrs[i].parse_list(&self.session.parse_sess,
- |parser| parser.parse_path(PathStyle::Mod));
+ let result = attrs[i].parse_list(&self.session.parse_sess, |parser| {
+ parser.parse_path_allowing_meta(PathStyle::Mod)
+ });
+
let mut traits = match result {
Ok(traits) => traits,
Err(mut e) => {
debug!("visit_expr {:?}", ex.node);
self.process_macro_use(ex.span, ex.id);
match ex.node {
- ast::ExprKind::Call(ref _f, ref _args) => {
- // Don't need to do anything for function calls,
- // because just walking the callee path does what we want.
- visit::walk_expr(self, ex);
- }
- ast::ExprKind::Path(_, ref path) => {
- self.process_path(ex.id, path, None);
- visit::walk_expr(self, ex);
- }
ast::ExprKind::Struct(ref path, ref fields, ref base) => {
let hir_expr = self.save_ctxt.tcx.hir.expect_expr(ex.id);
let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) {
self.visit_expr(element);
self.nest_tables(count.id, |v| v.visit_expr(count));
}
+ // In particular, we take this branch for call and path expressions,
+ // where we'll index the idents involved just by continuing to walk.
_ => {
visit::walk_expr(self, ex)
}
walk_list!(self, visit_ty, &l.ty);
walk_list!(self, visit_expr, &l.init);
}
+
+ fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
+ match item.node {
+ ast::ForeignItemKind::Fn(ref decl, ref generics) => {
+ if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
+ down_cast_data!(fn_data, FunctionData, item.span);
+ if !self.span.filter_generated(Some(fn_data.span), item.span) {
+ self.dumper.function(fn_data.clone().lower(self.tcx));
+ }
+
+ self.nest_tables(item.id, |v| v.process_formals(&decl.inputs,
+ &fn_data.qualname));
+ self.process_generic_params(generics, item.span, &fn_data.qualname, item.id);
+ }
+
+ for arg in &decl.inputs {
+ self.visit_ty(&arg.ty);
+ }
+
+ if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
+ self.visit_ty(&ret_ty);
+ }
+ }
+ ast::ForeignItemKind::Static(ref ty, _) => {
+ if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
+ down_cast_data!(var_data, VariableData, item.span);
+ if !self.span.filter_generated(Some(var_data.span), item.span) {
+ self.dumper.variable(var_data.lower(self.tcx));
+ }
+ }
+
+ self.visit_ty(ty);
+ }
+ }
+ }
}
result
}
+ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
+ let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+ match item.node {
+ ast::ForeignItemKind::Fn(ref decl, ref generics) => {
+ let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);
+ filter!(self.span_utils, sub_span, item.span, None);
+ Some(Data::FunctionData(FunctionData {
+ id: item.id,
+ name: item.ident.to_string(),
+ qualname: qualname,
+ declaration: None,
+ span: sub_span.unwrap(),
+ scope: self.enclosing_scope(item.id),
+ value: make_signature(decl, generics),
+ visibility: From::from(&item.vis),
+ parent: None,
+ docs: docs_for_attrs(&item.attrs),
+ sig: self.sig_base_extern(item),
+ attributes: item.attrs.clone(),
+ }))
+ }
+ ast::ForeignItemKind::Static(ref ty, m) => {
+ let keyword = if m { keywords::Mut } else { keywords::Static };
+ let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword);
+ filter!(self.span_utils, sub_span, item.span, None);
+ Some(Data::VariableData(VariableData {
+ id: item.id,
+ kind: VariableKind::Static,
+ name: item.ident.to_string(),
+ qualname: qualname,
+ span: sub_span.unwrap(),
+ scope: self.enclosing_scope(item.id),
+ parent: None,
+ value: String::new(),
+ type_value: ty_to_string(ty),
+ visibility: From::from(&item.vis),
+ docs: docs_for_attrs(&item.attrs),
+ sig: Some(self.sig_base_extern(item)),
+ attributes: item.attrs.clone(),
+ }))
+ }
+ }
+ }
+
pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
match item.node {
ast::ItemKind::Fn(ref decl, .., ref generics, _) => {
}
}
+ fn sig_base_extern(&self, item: &ast::ForeignItem) -> Signature {
+ let text = self.span_utils.signature_string_for_span(item.span);
+ let name = item.ident.to_string();
+ let ident_start = text.find(&name).expect("Name not in signature?");
+ let ident_end = ident_start + name.len();
+ Signature {
+ span: Span { hi: item.span.lo + BytePos(text.len() as u32), ..item.span },
+ text: text,
+ ident_start: ident_start,
+ ident_end: ident_end,
+ defs: vec![],
+ refs: vec![],
+ }
+ }
+
#[inline]
pub fn enclosing_scope(&self, id: NodeId) -> NodeId {
self.tcx.hir.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID)
use {ModuleSource, ModuleTranslation};
-const PARTITION_REUSED: &'static str = "rustc_partition_reused";
-const PARTITION_TRANSLATED: &'static str = "rustc_partition_translated";
+use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_TRANSLATED};
const MODULE: &'static str = "module";
const CFG: &'static str = "cfg";
impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
fn check_attr(&self, attr: &ast::Attribute) {
- let disposition = if attr.check_name(PARTITION_REUSED) {
+ let disposition = if attr.check_name(ATTR_PARTITION_REUSED) {
Disposition::Reused
- } else if attr.check_name(PARTITION_TRANSLATED) {
+ } else if attr.check_name(ATTR_PARTITION_TRANSLATED) {
Disposition::Translated
} else {
return;
}
{
- let mut linker = trans.linker_info.to_linker(&mut cmd, &sess);
+ let mut linker = trans.linker_info.to_linker(cmd, &sess);
link_args(&mut *linker, sess, crate_type, tmpdir,
objects, out_filename, outputs, trans);
+ cmd = linker.finalize();
}
cmd.args(&sess.target.target.options.late_link_args);
for obj in &sess.target.target.options.post_link_objects {
}
});
- let pair = sess.cstore.used_libraries().into_iter().filter(|l| {
+ let relevant_libs = sess.cstore.used_libraries().into_iter().filter(|l| {
relevant_lib(sess, l)
- }).partition(|lib| {
- lib.kind == NativeLibraryKind::NativeStatic
});
- let (staticlibs, others): (Vec<_>, Vec<_>) = pair;
-
- // Some platforms take hints about whether a library is static or dynamic.
- // For those that support this, we ensure we pass the option if the library
- // was flagged "static" (most defaults are dynamic) to ensure that if
- // libfoo.a and libfoo.so both exist that the right one is chosen.
- cmd.hint_static();
let search_path = archive_search_paths(sess);
- for l in staticlibs {
- // Here we explicitly ask that the entire archive is included into the
- // result artifact. For more details see #15460, but the gist is that
- // the linker will strip away any unused objects in the archive if we
- // don't otherwise explicitly reference them. This can occur for
- // libraries which are just providing bindings, libraries with generic
- // functions, etc.
- cmd.link_whole_staticlib(&l.name.as_str(), &search_path);
- }
-
- cmd.hint_dynamic();
-
- for lib in others {
+ for lib in relevant_libs {
match lib.kind {
NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()),
NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&lib.name.as_str()),
- NativeLibraryKind::NativeStatic => bug!(),
+ NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(&lib.name.as_str(),
+ &search_path)
}
}
}
}
pub fn to_linker(&'a self,
- cmd: &'a mut Command,
+ cmd: Command,
sess: &'a Session) -> Box<Linker+'a> {
if sess.target.target.options.is_like_msvc {
Box::new(MsvcLinker {
Box::new(GnuLinker {
cmd: cmd,
sess: sess,
- info: self
+ info: self,
+ hinted_static: false,
}) as Box<Linker>
}
}
fn no_default_libraries(&mut self);
fn build_dylib(&mut self, out_filename: &Path);
fn args(&mut self, args: &[String]);
- fn hint_static(&mut self);
- fn hint_dynamic(&mut self);
- fn whole_archives(&mut self);
- fn no_whole_archives(&mut self);
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
fn subsystem(&mut self, subsystem: &str);
+ // Should have been finalize(self), but we don't support self-by-value on trait objects (yet?).
+ fn finalize(&mut self) -> Command;
}
pub struct GnuLinker<'a> {
- cmd: &'a mut Command,
+ cmd: Command,
sess: &'a Session,
- info: &'a LinkerInfo
+ info: &'a LinkerInfo,
+ hinted_static: bool, // Keeps track of the current hinting mode.
}
impl<'a> GnuLinker<'a> {
fn takes_hints(&self) -> bool {
!self.sess.target.target.options.is_like_osx
}
+
+ // Some platforms take hints about whether a library is static or dynamic.
+ // For those that support this, we ensure we pass the option if the library
+ // was flagged "static" (most defaults are dynamic) to ensure that if
+ // libfoo.a and libfoo.so both exist that the right one is chosen.
+ fn hint_static(&mut self) {
+ if !self.takes_hints() { return }
+ if !self.hinted_static {
+ self.cmd.arg("-Wl,-Bstatic");
+ self.hinted_static = true;
+ }
+ }
+
+ fn hint_dynamic(&mut self) {
+ if !self.takes_hints() { return }
+ if self.hinted_static {
+ self.cmd.arg("-Wl,-Bdynamic");
+ self.hinted_static = false;
+ }
+ }
}
impl<'a> Linker for GnuLinker<'a> {
- fn link_dylib(&mut self, lib: &str) { self.cmd.arg("-l").arg(lib); }
- fn link_staticlib(&mut self, lib: &str) { self.cmd.arg("-l").arg(lib); }
- fn link_rlib(&mut self, lib: &Path) { self.cmd.arg(lib); }
+ fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg("-l").arg(lib); }
+ fn link_staticlib(&mut self, lib: &str) { self.hint_static(); self.cmd.arg("-l").arg(lib); }
+ fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); }
fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); }
fn framework_path(&mut self, path: &Path) { self.cmd.arg("-F").arg(path); }
fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); }
fn args(&mut self, args: &[String]) { self.cmd.args(args); }
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
+ self.hint_dynamic();
self.cmd.arg("-l").arg(lib);
}
fn link_framework(&mut self, framework: &str) {
+ self.hint_dynamic();
self.cmd.arg("-framework").arg(framework);
}
+ // Here we explicitly ask that the entire archive is included into the
+ // result artifact. For more details see #15460, but the gist is that
+ // the linker will strip away any unused objects in the archive if we
+ // don't otherwise explicitly reference them. This can occur for
+ // libraries which are just providing bindings, libraries with generic
+ // functions, etc.
fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]) {
+ self.hint_static();
let target = &self.sess.target.target;
if !target.options.is_like_osx {
self.cmd.arg("-Wl,--whole-archive")
}
fn link_whole_rlib(&mut self, lib: &Path) {
+ self.hint_static();
if self.sess.target.target.options.is_like_osx {
let mut v = OsString::from("-Wl,-force_load,");
v.push(lib);
}
}
- fn whole_archives(&mut self) {
- if !self.takes_hints() { return }
- self.cmd.arg("-Wl,--whole-archive");
- }
-
- fn no_whole_archives(&mut self) {
- if !self.takes_hints() { return }
- self.cmd.arg("-Wl,--no-whole-archive");
- }
-
- fn hint_static(&mut self) {
- if !self.takes_hints() { return }
- self.cmd.arg("-Wl,-Bstatic");
- }
-
- fn hint_dynamic(&mut self) {
- if !self.takes_hints() { return }
- self.cmd.arg("-Wl,-Bdynamic");
- }
-
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
// If we're compiling a dylib, then we let symbol visibility in object
// files to take care of whether they're exported or not.
fn subsystem(&mut self, subsystem: &str) {
self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem));
}
+
+ fn finalize(&mut self) -> Command {
+ self.hint_dynamic(); // Reset to default before returning the composed command line.
+ let mut cmd = Command::new("");
+ ::std::mem::swap(&mut cmd, &mut self.cmd);
+ cmd
+ }
}
pub struct MsvcLinker<'a> {
- cmd: &'a mut Command,
+ cmd: Command,
sess: &'a Session,
info: &'a LinkerInfo
}
self.cmd.arg("/DEBUG");
}
- fn whole_archives(&mut self) {
- // hints not supported?
- }
- fn no_whole_archives(&mut self) {
- // hints not supported?
- }
-
- // On windows static libraries are of the form `foo.lib` and dynamic
- // libraries are not linked against directly, but rather through their
- // import libraries also called `foo.lib`. As a result there's no
- // possibility for a native library to appear both dynamically and
- // statically in the same folder so we don't have to worry about hints like
- // we do on Unix platforms.
- fn hint_static(&mut self) {}
- fn hint_dynamic(&mut self) {}
-
// Currently the compiler doesn't use `dllexport` (an LLVM attribute) to
// export symbols from a dynamic library. When building a dynamic library,
// however, we're going to want some symbols exported, so this function
self.cmd.arg("/ENTRY:mainCRTStartup");
}
}
+
+ fn finalize(&mut self) -> Command {
+ let mut cmd = Command::new("");
+ ::std::mem::swap(&mut cmd, &mut self.cmd);
+ cmd
+ }
}
pub struct EmLinker<'a> {
- cmd: &'a mut Command,
+ cmd: Command,
sess: &'a Session,
info: &'a LinkerInfo
}
bug!("building dynamic library is unsupported on Emscripten")
}
- fn whole_archives(&mut self) {
- // noop
- }
-
- fn no_whole_archives(&mut self) {
- // noop
- }
-
- fn hint_static(&mut self) {
- // noop
- }
-
- fn hint_dynamic(&mut self) {
- // noop
- }
-
fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
let symbols = &self.info.exports[&crate_type];
fn subsystem(&mut self, _subsystem: &str) {
// noop
}
+
+ fn finalize(&mut self) -> Command {
+ let mut cmd = Command::new("");
+ ::std::mem::swap(&mut cmd, &mut self.cmd);
+ cmd
+ }
}
fn exported_symbols(scx: &SharedCrateContext,
let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
let slot = bcx.alloca(llretty, "personalityslot");
self.llpersonalityslot = Some(slot);
- Lifetime::Start.call(bcx, slot);
slot
}
}
let llretval = bcx.landing_pad(llretty, llpersonality, 1, self.llfn);
bcx.set_cleanup(llretval);
let slot = self.get_personality_slot(&bcx);
+ Lifetime::Start.call(&bcx, slot);
bcx.store(llretval, slot, None);
bcx.br(target_bb);
bcx.llbb()
let field_ty = field.ty(tcx, substs);
- if self.is_fn_ty(&field_ty, span) {
- err.help(&format!("use `({0}.{1})(...)` if you \
- meant to call the function \
- stored in the `{1}` field",
- expr_string,
- item_name));
+ if tcx.vis_is_accessible_from(field.vis, self.body_id) {
+ if self.is_fn_ty(&field_ty, span) {
+ err.help(&format!("use `({0}.{1})(...)` if you \
+ meant to call the function \
+ stored in the `{1}` field",
+ expr_string,
+ item_name));
+ } else {
+ err.help(&format!("did you mean to write `{0}.{1}` \
+ instead of `{0}.{1}(...)`?",
+ expr_string,
+ item_name));
+ }
+ err.span_label(span, &"field, not a method");
} else {
- err.help(&format!("did you mean to write `{0}.{1}` \
- instead of `{0}.{1}(...)`?",
- expr_string,
- item_name));
+ err.span_label(span, &"private field, not a method");
}
- err.span_label(span, &"field, not a method");
break;
}
}
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::lint;
use rustc::traits::{self, Reveal};
use rustc::ty::{self, TyCtxt};
for &item2 in &impl_items2[..] {
if (name, namespace) == name_and_namespace(item2) {
- let msg = format!("duplicate definitions with name `{}`", name);
- let node_id = self.tcx.hir.as_local_node_id(item1).unwrap();
- self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS,
- node_id,
- self.tcx.span_of_impl(item1).unwrap(),
- msg);
+ struct_span_err!(self.tcx.sess,
+ self.tcx.span_of_impl(item1).unwrap(),
+ E0592,
+ "duplicate definitions with name `{}`",
+ name)
+ .span_label(self.tcx.span_of_impl(item1).unwrap(),
+ &format!("duplicate definitions for `{}`", name))
+ .span_label(self.tcx.span_of_impl(item2).unwrap(),
+ &format!("other definition for `{}`", name))
+ .emit();
}
}
}
looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None);
}
}
+ if shorter.is_compact() {
+ break
+ }
}
buffer.push_str(&format!("<li>{}</li>", content));
}
fn list(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
- shorter: MarkdownOutputStyle) {
+ shorter: MarkdownOutputStyle, is_sorted_list: bool) {
debug!("List");
let mut content = String::new();
while let Some(event) = parser.next() {
looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None);
}
}
+ if shorter.is_compact() {
+ break
+ }
}
- buffer.push_str(&format!("<ul>{}</ul>", content));
+ buffer.push_str(&format!("<{0}>{1}</{0}>",
+ if is_sorted_list { "ol" } else { "ul" },
+ content));
}
fn emphasis(parser: &mut ParserWrapper, buffer: &mut String,
Event::Start(Tag::BlockQuote) => {
blockquote(parser, buffer, toc_builder, shorter);
}
- Event::Start(Tag::List(_)) => {
- list(parser, buffer, toc_builder, shorter);
+ Event::Start(Tag::List(x)) => {
+ list(parser, buffer, toc_builder, shorter, x.is_some());
}
Event::Start(Tag::Emphasis) => {
emphasis(parser, buffer, toc_builder, shorter, id);
// except according to those terms.
//! Operations on ASCII strings and characters.
+//!
+//! Most string operations in Rust act on UTF-8 strings. However, at times it
+//! makes more sense to only consider the ASCII character set for a specific
+//! operation.
+//!
+//! The [`AsciiExt`] trait provides methods that allow for character
+//! operations that only act on the ASCII subset and leave non-ASCII characters
+//! alone.
+//!
+//! The [`escape_default`] function provides an iterator over the bytes of an
+//! escaped version of the character given.
+//!
+//! [`AsciiExt`]: trait.AsciiExt.html
+//! [`escape_default`]: fn.escape_default.html
#![stable(feature = "rust1", since = "1.0.0")]
/// use std::ascii::AsciiExt;
///
/// let ascii = 'a';
- /// let utf8 = '❤';
+ /// let non_ascii = '❤';
/// let int_ascii = 97;
///
/// assert!(ascii.is_ascii());
- /// assert!(!utf8.is_ascii());
+ /// assert!(!non_ascii.is_ascii());
/// assert!(int_ascii.is_ascii());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
/// use std::ascii::AsciiExt;
///
/// let ascii = 'a';
- /// let utf8 = '❤';
+ /// let non_ascii = '❤';
/// let int_ascii = 97;
///
/// assert_eq!('A', ascii.to_ascii_uppercase());
- /// assert_eq!('❤', utf8.to_ascii_uppercase());
+ /// assert_eq!('❤', non_ascii.to_ascii_uppercase());
/// assert_eq!(65, int_ascii.to_ascii_uppercase());
/// ```
///
/// use std::ascii::AsciiExt;
///
/// let ascii = 'A';
- /// let utf8 = '❤';
+ /// let non_ascii = '❤';
/// let int_ascii = 65;
///
/// assert_eq!('a', ascii.to_ascii_lowercase());
- /// assert_eq!('❤', utf8.to_ascii_lowercase());
+ /// assert_eq!('❤', non_ascii.to_ascii_lowercase());
/// assert_eq!(97, int_ascii.to_ascii_lowercase());
/// ```
///
}
}
-/// An iterator over the escaped version of a byte, constructed via
-/// `std::ascii::escape_default`.
+/// An iterator over the escaped version of a byte.
+///
+/// This `struct` is created by the [`escape_default`] function. See its
+/// documentation for more.
+///
+/// [`escape_default`]: fn.escape_default.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct EscapeDefault {
range: Range<usize>,
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b't', escaped.next().unwrap());
+///
+/// let mut escaped = ascii::escape_default(b'\r');
+///
+/// assert_eq!(b'\\', escaped.next().unwrap());
+/// assert_eq!(b'r', escaped.next().unwrap());
+///
+/// let mut escaped = ascii::escape_default(b'\n');
+///
+/// assert_eq!(b'\\', escaped.next().unwrap());
+/// assert_eq!(b'n', escaped.next().unwrap());
+///
+/// let mut escaped = ascii::escape_default(b'\'');
+///
+/// assert_eq!(b'\\', escaped.next().unwrap());
+/// assert_eq!(b'\'', escaped.next().unwrap());
+///
+/// let mut escaped = ascii::escape_default(b'"');
+///
+/// assert_eq!(b'\\', escaped.next().unwrap());
+/// assert_eq!(b'"', escaped.next().unwrap());
+///
+/// let mut escaped = ascii::escape_default(b'\\');
+///
+/// assert_eq!(b'\\', escaped.next().unwrap());
+/// assert_eq!(b'\\', escaped.next().unwrap());
+///
+/// let mut escaped = ascii::escape_default(b'\x9d');
+///
+/// assert_eq!(b'\\', escaped.next().unwrap());
+/// assert_eq!(b'x', escaped.next().unwrap());
+/// assert_eq!(b'9', escaped.next().unwrap());
+/// assert_eq!(b'd', escaped.next().unwrap());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn escape_default(c: u8) -> EscapeDefault {
}
// Now we've done all our shifting. Return the value we grabbed earlier.
- (retkey, retval, gap.into_bucket().into_table())
+ (retkey, retval, gap.into_table())
}
/// Perform robin hood bucket stealing at the given `bucket`. You must
mut key: K,
mut val: V)
-> FullBucketMut<'a, K, V> {
- let start_index = bucket.index();
let size = bucket.table().size();
- // Save the *starting point*.
- let mut bucket = bucket.stash();
+ let raw_capacity = bucket.table().capacity();
// There can be at most `size - dib` buckets to displace, because
// in the worst case, there are `size` elements and we already are
// `displacement` buckets away from the initial one.
- let idx_end = start_index + size - bucket.displacement();
+ let idx_end = (bucket.index() + size - bucket.displacement()) % raw_capacity;
+ // Save the *starting point*.
+ let mut bucket = bucket.stash();
loop {
let (old_hash, old_key, old_val) = bucket.replace(hash, key, val);
// The caller should ensure that invariants by Robin Hood Hashing hold
// and that there's space in the underlying table.
fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) {
- let raw_cap = self.raw_capacity();
let mut buckets = Bucket::new(&mut self.table, hash);
- // note that buckets.index() keeps increasing
- // even if the pointer wraps back to the first bucket.
- let limit_bucket = buckets.index() + raw_cap;
+ let start_index = buckets.index();
loop {
// We don't need to compare hashes for value swap.
Full(b) => b.into_bucket(),
};
buckets.next();
- debug_assert!(buckets.index() < limit_bucket);
+ debug_assert!(buckets.index() != start_index);
}
}
}
pub fn retain<F>(&mut self, mut f: F)
where F: FnMut(&K, &mut V) -> bool
{
- if self.table.capacity() == 0 || self.table.size() == 0 {
+ if self.table.size() == 0 {
return;
}
+ let mut elems_left = self.table.size();
let mut bucket = Bucket::head_bucket(&mut self.table);
bucket.prev();
- let tail = bucket.index();
- loop {
+ let start_index = bucket.index();
+ while elems_left != 0 {
bucket = match bucket.peek() {
Full(mut full) => {
+ elems_left -= 1;
let should_remove = {
let (k, v) = full.read_mut();
!f(k, v)
};
if should_remove {
- let prev_idx = full.index();
let prev_raw = full.raw();
let (_, _, t) = pop_internal(full);
- Bucket::new_from(prev_raw, prev_idx, t)
+ Bucket::new_from(prev_raw, t)
} else {
full.into_bucket()
}
}
};
bucket.prev(); // reverse iteration
- if bucket.index() == tail {
- break;
- }
+ debug_assert!(elems_left == 0 || bucket.index() != start_index);
}
}
}
/// when the RawTable is created and is accessible with the `tag` and `set_tag`
/// functions.
pub struct RawTable<K, V> {
- capacity: usize,
+ capacity_mask: usize,
size: usize,
hashes: TaggedHashUintPtr,
unsafe impl<K: Send, V: Send> Send for RawTable<K, V> {}
unsafe impl<K: Sync, V: Sync> Sync for RawTable<K, V> {}
+// An unsafe view of a RawTable bucket
+// Valid indexes are within [0..table_capacity)
pub struct RawBucket<K, V> {
- hash: *mut HashUint,
+ hash_start: *mut HashUint,
// We use *const to ensure covariance with respect to K and V
- pair: *const (K, V),
+ pair_start: *const (K, V),
+ idx: usize,
_marker: marker::PhantomData<(K, V)>,
}
pub struct Bucket<K, V, M> {
raw: RawBucket<K, V>,
- idx: usize,
table: M,
}
pub struct EmptyBucket<K, V, M> {
raw: RawBucket<K, V>,
- idx: usize,
table: M,
}
pub struct FullBucket<K, V, M> {
raw: RawBucket<K, V>,
- idx: usize,
table: M,
}
assert_eq!(size_of::<SafeHash>(), size_of::<HashUint>())
}
+// RawBucket methods are unsafe as it's possible to
+// make a RawBucket point to invalid memory using safe code.
impl<K, V> RawBucket<K, V> {
- unsafe fn offset(self, count: isize) -> RawBucket<K, V> {
- RawBucket {
- hash: self.hash.offset(count),
- pair: self.pair.offset(count),
- _marker: marker::PhantomData,
- }
+ unsafe fn hash(&self) -> *mut HashUint {
+ self.hash_start.offset(self.idx as isize)
+ }
+ unsafe fn pair(&self) -> *mut (K, V) {
+ self.pair_start.offset(self.idx as isize) as *mut (K, V)
+ }
+ unsafe fn hash_pair(&self) -> (*mut HashUint, *mut (K, V)) {
+ (self.hash(), self.pair())
}
}
}
/// Get the raw index.
pub fn index(&self) -> usize {
- self.idx
+ self.raw.idx
}
/// Get the raw bucket.
pub fn raw(&self) -> RawBucket<K, V> {
impl<K, V, M> Bucket<K, V, M> {
/// Get the raw index.
pub fn index(&self) -> usize {
- self.idx
+ self.raw.idx
}
/// get the table.
pub fn into_table(self) -> M {
Bucket::at_index(table, hash.inspect() as usize)
}
- pub fn new_from(r: RawBucket<K, V>, i: usize, t: M)
+ pub fn new_from(r: RawBucket<K, V>, t: M)
-> Bucket<K, V, M>
{
Bucket {
raw: r,
- idx: i,
table: t,
}
}
// This is an uncommon case though, so avoid it in release builds.
debug_assert!(table.capacity() > 0,
"Table should have capacity at this point");
- let ib_index = ib_index & (table.capacity() - 1);
+ let ib_index = ib_index & table.capacity_mask;
Bucket {
- raw: unsafe { table.first_bucket_raw().offset(ib_index as isize) },
- idx: ib_index,
+ raw: table.raw_bucket_at(ib_index),
table: table,
}
}
pub fn first(table: M) -> Bucket<K, V, M> {
Bucket {
- raw: table.first_bucket_raw(),
- idx: 0,
+ raw: table.raw_bucket_at(0),
table: table,
}
}
/// the appropriate types to call most of the other functions in
/// this module.
pub fn peek(self) -> BucketState<K, V, M> {
- match unsafe { *self.raw.hash } {
+ match unsafe { *self.raw.hash() } {
EMPTY_BUCKET => {
Empty(EmptyBucket {
raw: self.raw,
- idx: self.idx,
table: self.table,
})
}
_ => {
Full(FullBucket {
raw: self.raw,
- idx: self.idx,
table: self.table,
})
}
}
}
- /// Modifies the bucket pointer in place to make it point to the next slot.
+ /// Modifies the bucket in place to make it point to the next slot.
pub fn next(&mut self) {
- self.idx += 1;
- let range = self.table.capacity();
- // This code is branchless thanks to a conditional move.
- let dist = if self.idx & (range - 1) == 0 {
- 1 - range as isize
- } else {
- 1
- };
- unsafe {
- self.raw = self.raw.offset(dist);
- }
+ self.raw.idx = self.raw.idx.wrapping_add(1) & self.table.capacity_mask;
}
- /// Modifies the bucket pointer in place to make it point to the previous slot.
+ /// Modifies the bucket in place to make it point to the previous slot.
pub fn prev(&mut self) {
- let range = self.table.capacity();
- let new_idx = self.idx.wrapping_sub(1) & (range - 1);
- let dist = (new_idx as isize).wrapping_sub(self.idx as isize);
- self.idx = new_idx;
- unsafe {
- self.raw = self.raw.offset(dist);
- }
+ self.raw.idx = self.raw.idx.wrapping_sub(1) & self.table.capacity_mask;
}
}
pub fn into_bucket(self) -> Bucket<K, V, M> {
Bucket {
raw: self.raw,
- idx: self.idx,
table: self.table,
}
}
pub fn gap_peek(self) -> Result<GapThenFull<K, V, M>, Bucket<K, V, M>> {
let gap = EmptyBucket {
raw: self.raw,
- idx: self.idx,
table: (),
};
/// Use `make_hash` to construct a `SafeHash` to pass to this function.
pub fn put(mut self, hash: SafeHash, key: K, value: V) -> FullBucket<K, V, M> {
unsafe {
- *self.raw.hash = hash.inspect();
- ptr::write(self.raw.pair as *mut (K, V), (key, value));
+ *self.raw.hash() = hash.inspect();
+ ptr::write(self.raw.pair(), (key, value));
self.table.borrow_table_mut().size += 1;
}
FullBucket {
raw: self.raw,
- idx: self.idx,
table: self.table,
}
}
/// Puts given key, remain value uninitialized.
/// It is only used for inplacement insertion.
pub unsafe fn put_key(mut self, hash: SafeHash, key: K) -> FullBucket<K, V, M> {
- *self.raw.hash = hash.inspect();
- let pair_mut = self.raw.pair as *mut (K, V);
- ptr::write(&mut (*pair_mut).0, key);
+ *self.raw.hash() = hash.inspect();
+ let pair_ptr = self.raw.pair();
+ ptr::write(&mut (*pair_ptr).0, key);
self.table.borrow_table_mut().size += 1;
FullBucket {
raw: self.raw,
- idx: self.idx,
table: self.table,
}
}
pub fn into_bucket(self) -> Bucket<K, V, M> {
Bucket {
raw: self.raw,
- idx: self.idx,
table: self.table,
}
}
pub fn stash(self) -> FullBucket<K, V, Self> {
FullBucket {
raw: self.raw,
- idx: self.idx,
table: self,
}
}
// Calculates the distance one has to travel when going from
// `hash mod capacity` onwards to `idx mod capacity`, wrapping around
// if the destination is not reached before the end of the table.
- (self.idx.wrapping_sub(self.hash().inspect() as usize)) & (self.table.capacity() - 1)
+ (self.raw.idx.wrapping_sub(self.hash().inspect() as usize)) & self.table.capacity_mask
}
#[inline]
pub fn hash(&self) -> SafeHash {
- unsafe { SafeHash { hash: *self.raw.hash } }
+ unsafe { SafeHash { hash: *self.raw.hash() } }
}
/// Gets references to the key and value at a given index.
pub fn read(&self) -> (&K, &V) {
- unsafe { (&(*self.raw.pair).0, &(*self.raw.pair).1) }
+ unsafe {
+ let pair_ptr = self.raw.pair();
+ (&(*pair_ptr).0, &(*pair_ptr).1)
+ }
}
}
self.table.size -= 1;
unsafe {
- *self.raw.hash = EMPTY_BUCKET;
- let (k, v) = ptr::read(self.raw.pair);
+ *self.raw.hash() = EMPTY_BUCKET;
+ let (k, v) = ptr::read(self.raw.pair());
(EmptyBucket {
raw: self.raw,
- idx: self.idx,
table: self.table,
},
k,
pub unsafe fn remove_key(&mut self) {
self.table.size -= 1;
- *self.raw.hash = EMPTY_BUCKET;
- let pair_mut = self.raw.pair as *mut (K, V);
- ptr::drop_in_place(&mut (*pair_mut).0); // only drop key
+ *self.raw.hash() = EMPTY_BUCKET;
+ let pair_ptr = self.raw.pair();
+ ptr::drop_in_place(&mut (*pair_ptr).0); // only drop key
}
}
{
pub fn replace(&mut self, h: SafeHash, k: K, v: V) -> (SafeHash, K, V) {
unsafe {
- let old_hash = ptr::replace(self.raw.hash as *mut SafeHash, h);
- let (old_key, old_val) = ptr::replace(self.raw.pair as *mut (K, V), (k, v));
+ let old_hash = ptr::replace(self.raw.hash() as *mut SafeHash, h);
+ let (old_key, old_val) = ptr::replace(self.raw.pair(), (k, v));
(old_hash, old_key, old_val)
}
{
/// Gets mutable references to the key and value at a given index.
pub fn read_mut(&mut self) -> (&mut K, &mut V) {
- let pair_mut = self.raw.pair as *mut (K, V);
- unsafe { (&mut (*pair_mut).0, &mut (*pair_mut).1) }
+ unsafe {
+ let pair_ptr = self.raw.pair();
+ (&mut (*pair_ptr).0, &mut (*pair_ptr).1)
+ }
}
}
/// in exchange for this, the returned references have a longer lifetime
/// than the references returned by `read()`.
pub fn into_refs(self) -> (&'t K, &'t V) {
- unsafe { (&(*self.raw.pair).0, &(*self.raw.pair).1) }
+ unsafe {
+ let pair_ptr = self.raw.pair();
+ (&(*pair_ptr).0, &(*pair_ptr).1)
+ }
}
}
/// This works similarly to `into_refs`, exchanging a bucket state
/// for mutable references into the table.
pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) {
- let pair_mut = self.raw.pair as *mut (K, V);
- unsafe { (&mut (*pair_mut).0, &mut (*pair_mut).1) }
+ unsafe {
+ let pair_ptr = self.raw.pair();
+ (&mut (*pair_ptr).0, &mut (*pair_ptr).1)
+ }
}
}
&self.full
}
- pub fn into_bucket(self) -> Bucket<K, V, M> {
- self.full.into_bucket()
+ pub fn into_table(self) -> M {
+ self.full.into_table()
}
pub fn shift(mut self) -> Result<GapThenFull<K, V, M>, Bucket<K, V, M>> {
unsafe {
- *self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET);
- ptr::copy_nonoverlapping(self.full.raw.pair, self.gap.raw.pair as *mut (K, V), 1);
+ let (gap_hash, gap_pair) = self.gap.raw.hash_pair();
+ let (full_hash, full_pair) = self.full.raw.hash_pair();
+ *gap_hash = mem::replace(&mut *full_hash, EMPTY_BUCKET);
+ ptr::copy_nonoverlapping(full_pair, gap_pair, 1);
}
- let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full;
+ let FullBucket { raw: prev_raw, .. } = self.full;
match self.full.next().peek() {
Full(bucket) => {
self.gap.raw = prev_raw;
- self.gap.idx = prev_idx;
self.full = bucket;
if capacity == 0 {
return RawTable {
size: 0,
- capacity: 0,
+ capacity_mask: capacity.wrapping_sub(1),
hashes: TaggedHashUintPtr::new(EMPTY as *mut HashUint),
marker: marker::PhantomData,
};
let hashes = buffer.offset(hash_offset as isize) as *mut HashUint;
RawTable {
- capacity: capacity,
+ capacity_mask: capacity.wrapping_sub(1),
size: 0,
hashes: TaggedHashUintPtr::new(hashes),
marker: marker::PhantomData,
}
}
- fn first_bucket_raw(&self) -> RawBucket<K, V> {
- let hashes_size = self.capacity * size_of::<HashUint>();
- let pairs_size = self.capacity * size_of::<(K, V)>();
+ fn raw_bucket_at(&self, index: usize) -> RawBucket<K, V> {
+ let hashes_size = self.capacity() * size_of::<HashUint>();
+ let pairs_size = self.capacity() * size_of::<(K, V)>();
- let buffer = self.hashes.ptr() as *mut u8;
let (pairs_offset, _, oflo) =
calculate_offsets(hashes_size, pairs_size, align_of::<(K, V)>());
debug_assert!(!oflo, "capacity overflow");
+
+ let buffer = self.hashes.ptr() as *mut u8;
unsafe {
RawBucket {
- hash: self.hashes.ptr(),
- pair: buffer.offset(pairs_offset as isize) as *const _,
+ hash_start: buffer as *mut HashUint,
+ pair_start: buffer.offset(pairs_offset as isize) as *const (K, V),
+ idx: index,
_marker: marker::PhantomData,
}
}
/// The hashtable's capacity, similar to a vector's.
pub fn capacity(&self) -> usize {
- self.capacity
+ self.capacity_mask.wrapping_add(1)
}
/// The number of elements ever `put` in the hashtable, minus the number
fn raw_buckets(&self) -> RawBuckets<K, V> {
RawBuckets {
- raw: self.first_bucket_raw(),
- hashes_end: unsafe { self.hashes.ptr().offset(self.capacity as isize) },
+ raw: self.raw_bucket_at(0),
+ elems_left: self.size,
marker: marker::PhantomData,
}
}
pub fn iter(&self) -> Iter<K, V> {
Iter {
iter: self.raw_buckets(),
- elems_left: self.size(),
}
}
pub fn iter_mut(&mut self) -> IterMut<K, V> {
IterMut {
iter: self.raw_buckets(),
- elems_left: self.size(),
_marker: marker::PhantomData,
}
}
pub fn into_iter(self) -> IntoIter<K, V> {
- let RawBuckets { raw, hashes_end, .. } = self.raw_buckets();
+ let RawBuckets { raw, elems_left, .. } = self.raw_buckets();
// Replace the marker regardless of lifetime bounds on parameters.
IntoIter {
iter: RawBuckets {
raw: raw,
- hashes_end: hashes_end,
+ elems_left: elems_left,
marker: marker::PhantomData,
},
table: self,
}
pub fn drain(&mut self) -> Drain<K, V> {
- let RawBuckets { raw, hashes_end, .. } = self.raw_buckets();
+ let RawBuckets { raw, elems_left, .. } = self.raw_buckets();
// Replace the marker regardless of lifetime bounds on parameters.
Drain {
iter: RawBuckets {
raw: raw,
- hashes_end: hashes_end,
+ elems_left: elems_left,
marker: marker::PhantomData,
},
table: unsafe { Shared::new(self) },
/// state and should only be used for dropping the table's remaining
/// entries. It's used in the implementation of Drop.
unsafe fn rev_drop_buckets(&mut self) {
- let first_raw = self.first_bucket_raw();
- let mut raw = first_raw.offset(self.capacity as isize);
+ // initialize the raw bucket past the end of the table
+ let mut raw = self.raw_bucket_at(self.capacity());
let mut elems_left = self.size;
while elems_left != 0 {
- debug_assert!(raw.hash != first_raw.hash);
+ raw.idx -= 1;
- raw = raw.offset(-1);
-
- if *raw.hash != EMPTY_BUCKET {
+ if *raw.hash() != EMPTY_BUCKET {
elems_left -= 1;
- ptr::drop_in_place(raw.pair as *mut (K, V));
+ ptr::drop_in_place(raw.pair());
}
}
}
/// this interface is safe, it's not used outside this module.
struct RawBuckets<'a, K, V> {
raw: RawBucket<K, V>,
- hashes_end: *mut HashUint,
+ elems_left: usize,
// Strictly speaking, this should be &'a (K,V), but that would
// require that K:'a, and we often use RawBuckets<'static...> for
fn clone(&self) -> RawBuckets<'a, K, V> {
RawBuckets {
raw: self.raw,
- hashes_end: self.hashes_end,
+ elems_left: self.elems_left,
marker: marker::PhantomData,
}
}
type Item = RawBucket<K, V>;
fn next(&mut self) -> Option<RawBucket<K, V>> {
- while self.raw.hash != self.hashes_end {
+ if self.elems_left == 0 {
+ return None;
+ }
+
+ loop {
unsafe {
- // We are swapping out the pointer to a bucket and replacing
- // it with the pointer to the next one.
- let prev = ptr::replace(&mut self.raw, self.raw.offset(1));
- if *prev.hash != EMPTY_BUCKET {
- return Some(prev);
+ let item = self.raw;
+ self.raw.idx += 1;
+ if *item.hash() != EMPTY_BUCKET {
+ self.elems_left -= 1;
+ return Some(item);
}
}
}
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.elems_left, Some(self.elems_left))
+ }
+}
- None
+impl<'a, K, V> ExactSizeIterator for RawBuckets<'a, K, V> {
+ fn len(&self) -> usize {
+ self.elems_left
}
}
/// Iterator over shared references to entries in a table.
pub struct Iter<'a, K: 'a, V: 'a> {
iter: RawBuckets<'a, K, V>,
- elems_left: usize,
}
unsafe impl<'a, K: Sync, V: Sync> Sync for Iter<'a, K, V> {}
fn clone(&self) -> Iter<'a, K, V> {
Iter {
iter: self.iter.clone(),
- elems_left: self.elems_left,
}
}
}
-
/// Iterator over mutable references to entries in a table.
pub struct IterMut<'a, K: 'a, V: 'a> {
iter: RawBuckets<'a, K, V>,
- elems_left: usize,
// To ensure invariance with respect to V
_marker: marker::PhantomData<&'a mut V>,
}
pub fn iter(&self) -> Iter<K, V> {
Iter {
iter: self.iter.clone(),
- elems_left: self.elems_left,
}
}
}
pub fn iter(&self) -> Iter<K, V> {
Iter {
iter: self.iter.clone(),
- elems_left: self.table.size,
}
}
}
impl<'a, K, V> Drain<'a, K, V> {
pub fn iter(&self) -> Iter<K, V> {
- unsafe {
- Iter {
- iter: self.iter.clone(),
- elems_left: (**self.table).size,
- }
+ Iter {
+ iter: self.iter.clone(),
}
}
}
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<(&'a K, &'a V)> {
- self.iter.next().map(|bucket| {
- self.elems_left -= 1;
- unsafe { (&(*bucket.pair).0, &(*bucket.pair).1) }
+ self.iter.next().map(|raw| unsafe {
+ let pair_ptr = raw.pair();
+ (&(*pair_ptr).0, &(*pair_ptr).1)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
- (self.elems_left, Some(self.elems_left))
+ self.iter.size_hint()
}
}
+
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
fn len(&self) -> usize {
- self.elems_left
+ self.iter.len()
}
}
type Item = (&'a K, &'a mut V);
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
- self.iter.next().map(|bucket| {
- self.elems_left -= 1;
- let pair_mut = bucket.pair as *mut (K, V);
- unsafe { (&(*pair_mut).0, &mut (*pair_mut).1) }
+ self.iter.next().map(|raw| unsafe {
+ let pair_ptr = raw.pair();
+ (&(*pair_ptr).0, &mut (*pair_ptr).1)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
- (self.elems_left, Some(self.elems_left))
+ self.iter.size_hint()
}
}
+
impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
fn len(&self) -> usize {
- self.elems_left
+ self.iter.len()
}
}
type Item = (SafeHash, K, V);
fn next(&mut self) -> Option<(SafeHash, K, V)> {
- self.iter.next().map(|bucket| {
+ self.iter.next().map(|raw| {
self.table.size -= 1;
unsafe {
- let (k, v) = ptr::read(bucket.pair);
- (SafeHash { hash: *bucket.hash }, k, v)
+ let (k, v) = ptr::read(raw.pair());
+ (SafeHash { hash: *raw.hash() }, k, v)
}
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
- let size = self.table.size();
- (size, Some(size))
+ self.iter.size_hint()
}
}
+
impl<K, V> ExactSizeIterator for IntoIter<K, V> {
fn len(&self) -> usize {
- self.table.size()
+ self.iter().len()
}
}
#[inline]
fn next(&mut self) -> Option<(SafeHash, K, V)> {
- self.iter.next().map(|bucket| {
- unsafe {
- (*self.table.as_mut_ptr()).size -= 1;
- let (k, v) = ptr::read(bucket.pair);
- (SafeHash { hash: ptr::replace(bucket.hash, EMPTY_BUCKET) }, k, v)
- }
+ self.iter.next().map(|raw| unsafe {
+ (*self.table.as_mut_ptr()).size -= 1;
+ let (k, v) = ptr::read(raw.pair());
+ (SafeHash { hash: ptr::replace(&mut *raw.hash(), EMPTY_BUCKET) }, k, v)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
- let size = unsafe { (**self.table).size() };
- (size, Some(size))
+ self.iter.size_hint()
}
}
+
impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
fn len(&self) -> usize {
- unsafe { (**self.table).size() }
+ self.iter.len()
}
}
impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
fn clone(&self) -> RawTable<K, V> {
unsafe {
- let mut new_ht = RawTable::new_uninitialized(self.capacity());
-
- {
- let cap = self.capacity();
- let mut new_buckets = Bucket::first(&mut new_ht);
- let mut buckets = Bucket::first(self);
- while buckets.index() != cap {
- match buckets.peek() {
- Full(full) => {
- let (h, k, v) = {
- let (k, v) = full.read();
- (full.hash(), k.clone(), v.clone())
- };
- *new_buckets.raw.hash = h.inspect();
- ptr::write(new_buckets.raw.pair as *mut (K, V), (k, v));
- }
- Empty(..) => {
- *new_buckets.raw.hash = EMPTY_BUCKET;
- }
- }
- new_buckets.next();
- buckets.next();
+ let cap = self.capacity();
+ let mut new_ht = RawTable::new_uninitialized(cap);
+
+ let mut new_buckets = new_ht.raw_bucket_at(0);
+ let mut buckets = self.raw_bucket_at(0);
+ while buckets.idx < cap {
+ *new_buckets.hash() = *buckets.hash();
+ if *new_buckets.hash() != EMPTY_BUCKET {
+ let pair_ptr = buckets.pair();
+ let kv = ((*pair_ptr).0.clone(), (*pair_ptr).1.clone());
+ ptr::write(new_buckets.pair(), kv);
}
- };
+ buckets.idx += 1;
+ new_buckets.idx += 1;
+ }
new_ht.size = self.size();
unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> {
fn drop(&mut self) {
- if self.capacity == 0 {
+ if self.capacity() == 0 {
return;
}
}
}
- let hashes_size = self.capacity * size_of::<HashUint>();
- let pairs_size = self.capacity * size_of::<(K, V)>();
+ let hashes_size = self.capacity() * size_of::<HashUint>();
+ let pairs_size = self.capacity() * size_of::<(K, V)>();
let (align, _, size, oflo) = calculate_allocation(hashes_size,
align_of::<HashUint>(),
pairs_size,
}
}
- /// Indicate that directories create should be created recursively, creating
- /// all parent directories if they do not exist with the same security and
- /// permissions settings.
+ /// Indicates that directories should be created recursively, creating all
+ /// parent directories. Parents that do not exist are created with the same
+ /// security and permissions settings.
///
/// This option defaults to `false`.
///
/// Create the specified directory with the options configured in this
/// builder.
///
+ /// It is considered an error if the directory already exists unless
+ /// recursive mode is enabled.
+ ///
/// # Examples
///
/// ```no_run
generation_id: usize,
}
-/// A result returned from wait.
+/// A `BarrierWaitResult` is returned by [`wait`] when all threads in the [`Barrier`]
+/// have rendezvoused.
///
-/// Currently this opaque structure only has one method, [`.is_leader`]. Only
-/// one thread will receive a result that will return `true` from this function.
-///
-/// [`.is_leader`]: #method.is_leader
+/// [`wait`]: struct.Barrier.html#method.wait
+/// [`Barrier`]: struct.Barrier.html
///
/// # Examples
///
//! This module provides message-based communication over channels, concretely
//! defined among three types:
//!
-//! * `Sender`
-//! * `SyncSender`
-//! * `Receiver`
+//! * [`Sender`]
+//! * [`SyncSender`]
+//! * [`Receiver`]
//!
-//! A `Sender` or `SyncSender` is used to send data to a `Receiver`. Both
+//! A [`Sender`] or [`SyncSender`] is used to send data to a [`Receiver`]. Both
//! senders are clone-able (multi-producer) such that many threads can send
//! simultaneously to one receiver (single-consumer).
//!
//! These channels come in two flavors:
//!
-//! 1. An asynchronous, infinitely buffered channel. The `channel()` function
+//! 1. An asynchronous, infinitely buffered channel. The [`channel`] function
//! will return a `(Sender, Receiver)` tuple where all sends will be
//! **asynchronous** (they never block). The channel conceptually has an
//! infinite buffer.
//!
-//! 2. A synchronous, bounded channel. The `sync_channel()` function will return
-//! a `(SyncSender, Receiver)` tuple where the storage for pending messages
-//! is a pre-allocated buffer of a fixed size. All sends will be
+//! 2. A synchronous, bounded channel. The [`sync_channel`] function will
+//! return a `(SyncSender, Receiver)` tuple where the storage for pending
+//! messages is a pre-allocated buffer of a fixed size. All sends will be
//! **synchronous** by blocking until there is buffer space available. Note
-//! that a bound of 0 is allowed, causing the channel to become a
-//! "rendezvous" channel where each sender atomically hands off a message to
-//! a receiver.
+//! that a bound of 0 is allowed, causing the channel to become a "rendezvous"
+//! channel where each sender atomically hands off a message to a receiver.
+//!
+//! [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html
+//! [`SyncSender`]: ../../../std/sync/mpsc/struct.SyncSender.html
+//! [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html
+//! [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
+//! [`channel`]: ../../../std/sync/mpsc/fn.channel.html
+//! [`sync_channel`]: ../../../std/sync/mpsc/fn.sync_channel.html
//!
//! ## Disconnection
//!
-//! The send and receive operations on channels will all return a `Result`
+//! The send and receive operations on channels will all return a [`Result`]
//! indicating whether the operation succeeded or not. An unsuccessful operation
//! is normally indicative of the other half of a channel having "hung up" by
//! being dropped in its corresponding thread.
//!
//! Once half of a channel has been deallocated, most operations can no longer
-//! continue to make progress, so `Err` will be returned. Many applications will
-//! continue to `unwrap()` the results returned from this module, instigating a
-//! propagation of failure among threads if one unexpectedly dies.
+//! continue to make progress, so [`Err`] will be returned. Many applications
+//! will continue to [`unwrap`] the results returned from this module,
+//! instigating a propagation of failure among threads if one unexpectedly dies.
+//!
+//! [`Result`]: ../../../std/result/enum.Result.html
+//! [`Err`]: ../../../std/result/enum.Result.html#variant.Err
+//! [`unwrap`]: ../../../std/result/enum.Result.html#method.unwrap
//!
//! # Examples
//!
mod spsc_queue;
/// The receiving-half of Rust's channel type. This half can only be owned by
-/// one thread
+/// one thread.
+///
+/// Messages sent to the channel can be retrieved using [`recv`].
+///
+/// [`recv`]: ../../../std/sync/mpsc/struct.Receiver.html#method.recv
+///
+/// # Examples
+///
+/// ```rust
+/// use std::sync::mpsc::channel;
+/// use std::thread;
+/// use std::time::Duration;
+///
+/// let (send, recv) = channel();
+///
+/// thread::spawn(move || {
+/// send.send("Hello world!").unwrap();
+/// thread::sleep(Duration::from_secs(2)); // block for two seconds
+/// send.send("Delayed for 2 seconds").unwrap();
+/// });
+///
+/// println!("{}", recv.recv().unwrap()); // Received immediately
+/// println!("Waiting...");
+/// println!("{}", recv.recv().unwrap()); // Received after 2 seconds
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Receiver<T> {
inner: UnsafeCell<Flavor<T>>,
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> !Sync for Receiver<T> { }
-/// An iterator over messages on a receiver, this iterator will block
-/// whenever `next` is called, waiting for a new message, and `None` will be
-/// returned when the corresponding channel has hung up.
+/// An iterator over messages on a receiver, this iterator will block whenever
+/// [`next`] is called, waiting for a new message, and [`None`] will be returned
+/// when the corresponding channel has hung up.
+///
+/// [`next`]: ../../../std/iter/trait.Iterator.html#tymethod.next
+/// [`None`]: ../../../std/option/enum.Option.html#variant.None
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Iter<'a, T: 'a> {
}
/// An iterator that attempts to yield all pending values for a receiver.
-/// `None` will be returned when there are no pending values remaining or
-/// if the corresponding channel has hung up.
+/// [`None`] will be returned when there are no pending values remaining or if
+/// the corresponding channel has hung up.
///
/// This Iterator will never block the caller in order to wait for data to
-/// become available. Instead, it will return `None`.
+/// become available. Instead, it will return [`None`].
+///
+/// [`None`]: ../../../std/option/enum.Option.html#variant.None
#[stable(feature = "receiver_try_iter", since = "1.15.0")]
#[derive(Debug)]
pub struct TryIter<'a, T: 'a> {
}
/// An owning iterator over messages on a receiver, this iterator will block
-/// whenever `next` is called, waiting for a new message, and `None` will be
+/// whenever [`next`] is called, waiting for a new message, and [`None`] will be
/// returned when the corresponding channel has hung up.
+///
+/// [`next`]: ../../../std/iter/trait.Iterator.html#tymethod.next
+/// [`None`]: ../../../std/option/enum.Option.html#variant.None
+///
#[stable(feature = "receiver_into_iter", since = "1.1.0")]
#[derive(Debug)]
pub struct IntoIter<T> {
/// The sending-half of Rust's asynchronous channel type. This half can only be
/// owned by one thread, but it can be cloned to send to other threads.
+///
+/// Messages can be sent through this channel with [`send`].
+///
+/// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
+///
+/// # Examples
+///
+/// ```rust
+/// use std::sync::mpsc::channel;
+/// use std::thread;
+///
+/// let (sender, receiver) = channel();
+/// let sender2 = sender.clone();
+///
+/// // First thread owns sender
+/// thread::spawn(move || {
+/// sender.send(1).unwrap();
+/// });
+///
+/// // Second thread owns sender2
+/// thread::spawn(move || {
+/// sender2.send(2).unwrap();
+/// });
+///
+/// let msg = receiver.recv().unwrap();
+/// let msg2 = receiver.recv().unwrap();
+///
+/// assert_eq!(3, msg + msg2);
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sender<T> {
inner: UnsafeCell<Flavor<T>>,
/// The sending-half of Rust's synchronous channel type. This half can only be
/// owned by one thread, but it can be cloned to send to other threads.
+///
+/// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
+/// [`SyncSender::send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send
+///
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SyncSender<T> {
inner: Arc<sync::Packet<T>>,
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> !Sync for SyncSender<T> {}
-/// An error returned from the `send` function on channels.
+/// An error returned from the [`send`] function on channels.
///
-/// A `send` operation can only fail if the receiving end of a channel is
+/// A [`send`] operation can only fail if the receiving end of a channel is
/// disconnected, implying that the data could never be received. The error
/// contains the data being sent as a payload so it can be recovered.
+///
+/// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(PartialEq, Eq, Clone, Copy)]
pub struct SendError<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
-/// An error returned from the `recv` function on a `Receiver`.
+/// An error returned from the [`recv`] function on a [`Receiver`].
///
-/// The `recv` operation can only fail if the sending half of a channel is
+/// The [`recv`] operation can only fail if the sending half of a channel is
/// disconnected, implying that no further messages will ever be received.
+///
+/// [`recv`]: ../../../std/sync/mpsc/struct.Receiver.html#method.recv
+/// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RecvError;
-/// This enumeration is the list of the possible reasons that `try_recv` could
+/// This enumeration is the list of the possible reasons that [`try_recv`] could
/// not return data when called.
+///
+/// [`try_recv`]: ../../../std/sync/mpsc/struct.Receiver.html#method.try_recv
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum TryRecvError {
Disconnected,
}
-/// This enumeration is the list of possible errors that `recv_timeout` could
+/// This enumeration is the list of possible errors that [`recv_timeout`] could
/// not return data when called.
+///
+/// [`recv_timeout`]: ../../../std/sync/mpsc/struct.Receiver.html#method.recv_timeout
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[stable(feature = "mpsc_recv_timeout", since = "1.12.0")]
pub enum RecvTimeoutError {
}
/// This enumeration is the list of the possible error outcomes for the
-/// `SyncSender::try_send` method.
+/// [`SyncSender::try_send`] method.
+///
+/// [`SyncSender::try_send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.try_send
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum TrySendError<T> {
/// A successful send occurs when it is determined that the other end of
/// the channel has not hung up already. An unsuccessful send would be one
/// where the corresponding receiver has already been deallocated. Note
- /// that a return value of `Err` means that the data will never be
- /// received, but a return value of `Ok` does *not* mean that the data
+ /// that a return value of [`Err`] means that the data will never be
+ /// received, but a return value of [`Ok`] does *not* mean that the data
/// will be received. It is possible for the corresponding receiver to
- /// hang up immediately after this function returns `Ok`.
+ /// hang up immediately after this function returns [`Ok`].
+ ///
+ /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
+ /// [`Ok`]: ../../../std/result/enum.Result.html#variant.Ok
///
/// This method will never block the current thread.
///
/// time. If the buffer size is 0, however, it can be guaranteed that the
/// receiver has indeed received the data if this function returns success.
///
- /// This function will never panic, but it may return `Err` if the
- /// `Receiver` has disconnected and is no longer able to receive
+ /// This function will never panic, but it may return [`Err`] if the
+ /// [`Receiver`] has disconnected and is no longer able to receive
/// information.
+ ///
+ /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
+ /// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn send(&self, t: T) -> Result<(), SendError<T>> {
self.inner.send(t).map_err(SendError)
/// Attempts to send a value on this channel without blocking.
///
- /// This method differs from `send` by returning immediately if the
+ /// This method differs from [`send`] by returning immediately if the
/// channel's buffer is full or no receiver is waiting to acquire some
- /// data. Compared with `send`, this function has two failure cases
+ /// data. Compared with [`send`], this function has two failure cases
/// instead of one (one for disconnection, one for a full buffer).
///
- /// See `SyncSender::send` for notes about guarantees of whether the
+ /// See [`SyncSender::send`] for notes about guarantees of whether the
/// receiver has received the data or not if this function is successful.
+ ///
+ /// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
+ /// [`SyncSender::send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send
#[stable(feature = "rust1", since = "1.0.0")]
pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
self.inner.try_send(t)
///
/// This function will always block the current thread if there is no data
/// available and it's possible for more data to be sent. Once a message is
- /// sent to the corresponding `Sender`, then this receiver will wake up and
+ /// sent to the corresponding [`Sender`], then this receiver will wake up and
/// return that message.
///
- /// If the corresponding `Sender` has disconnected, or it disconnects while
- /// this call is blocking, this call will wake up and return `Err` to
+ /// If the corresponding [`Sender`] has disconnected, or it disconnects while
+ /// this call is blocking, this call will wake up and return [`Err`] to
/// indicate that no more messages can ever be received on this channel.
/// However, since channels are buffered, messages sent before the disconnect
/// will still be properly received.
///
+ /// [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html
+ /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
+ ///
/// # Examples
///
/// ```
///
/// This function will always block the current thread if there is no data
/// available and it's possible for more data to be sent. Once a message is
- /// sent to the corresponding `Sender`, then this receiver will wake up and
+ /// sent to the corresponding [`Sender`], then this receiver will wake up and
/// return that message.
///
- /// If the corresponding `Sender` has disconnected, or it disconnects while
- /// this call is blocking, this call will wake up and return `Err` to
+ /// If the corresponding [`Sender`] has disconnected, or it disconnects while
+ /// this call is blocking, this call will wake up and return [`Err`] to
/// indicate that no more messages can ever be received on this channel.
/// However, since channels are buffered, messages sent before the disconnect
/// will still be properly received.
///
+ /// [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html
+ /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
+ ///
/// # Examples
///
/// ```no_run
}
/// Returns an iterator that will block waiting for messages, but never
- /// `panic!`. It will return `None` when the channel has hung up.
+ /// [`panic!`]. It will return [`None`] when the channel has hung up.
+ ///
+ /// [`panic!`]: ../../../std/macro.panic.html
+ /// [`None`]: ../../../std/option/enum.Option.html#variant.None
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::sync::mpsc::channel;
+ /// use std::thread;
+ ///
+ /// let (send, recv) = channel();
+ ///
+ /// thread::spawn(move || {
+ /// send.send(1u8).unwrap();
+ /// send.send(2u8).unwrap();
+ /// send.send(3u8).unwrap();
+ /// });
+ ///
+ /// for x in recv.iter() {
+ /// println!("Got: {}", x);
+ /// }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn iter(&self) -> Iter<T> {
Iter { rx: self }
/// Returns an iterator that will attempt to yield all pending values.
/// It will return `None` if there are no more pending values or if the
- /// channel has hung up. The iterator will never `panic!` or block the
+ /// channel has hung up. The iterator will never [`panic!`] or block the
/// user by waiting for values.
+ ///
+ /// [`panic!`]: ../../../std/macro.panic.html
#[stable(feature = "receiver_try_iter", since = "1.15.0")]
pub fn try_iter(&self) -> TryIter<T> {
TryIter { rx: self }
///
/// The mutexes in this module implement a strategy called "poisoning" where a
/// mutex is considered poisoned whenever a thread panics while holding the
-/// lock. Once a mutex is poisoned, all other threads are unable to access the
+/// mutex. Once a mutex is poisoned, all other threads are unable to access the
/// data by default as it is likely tainted (some invariant is not being
/// upheld).
///
// Note that this mutex is in a *box*, not inlined into the struct itself.
// Once a native mutex has been used once, its address can never change (it
// can't be moved). This mutex type can be safely moved at any time, so to
- // ensure that the native mutex is used correctly we box the inner lock to
+ // ensure that the native mutex is used correctly we box the inner mutex to
// give it a constant address.
inner: Box<sys::Mutex>,
poison: poison::Flag,
/// Acquires a mutex, blocking the current thread until it is able to do so.
///
/// This function will block the local thread until it is available to acquire
- /// the mutex. Upon returning, the thread is the only thread with the mutex
+ /// the mutex. Upon returning, the thread is the only thread with the lock
/// held. An RAII guard is returned to allow scoped unlock of the lock. When
/// the guard goes out of scope, the mutex will be unlocked.
///
}
}
- /// Determines whether the lock is poisoned.
+ /// Determines whether the mutex is poisoned.
///
- /// If another thread is active, the lock can still become poisoned at any
+ /// If another thread is active, the mutex can still become poisoned at any
/// time. You should not trust a `false` value for program correctness
/// without additional synchronization.
///
#[stable(feature = "mutex_into_inner", since = "1.6.0")]
pub fn into_inner(self) -> LockResult<T> where T: Sized {
// We know statically that there are no outstanding references to
- // `self` so there's no need to lock the inner lock.
+ // `self` so there's no need to lock the inner mutex.
//
// To get the inner value, we'd like to call `data.into_inner()`,
// but because `Mutex` impl-s `Drop`, we can't move out of it, so
#[stable(feature = "mutex_get_mut", since = "1.6.0")]
pub fn get_mut(&mut self) -> LockResult<&mut T> {
// We know statically that there are no other references to `self`, so
- // there's no need to lock the inner lock.
+ // there's no need to lock the inner mutex.
let data = unsafe { &mut *self.data.get() };
poison::map_result(self.poison.borrow(), |_| data )
}
fn into_raw_fd(self) -> RawFd;
}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for RawFd {
- fn as_raw_fd(&self) -> RawFd {
- *self
- }
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for fs::File {
fn as_raw_fd(&self) -> RawFd {
fs::File::from_inner(sys::fs::File::from_inner(fd))
}
}
-
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for RawFd {
- fn into_raw_fd(self) -> RawFd {
- self
- }
-}
-
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for fs::File {
fn into_raw_fd(self) -> RawFd {
#[cfg(not(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia")))]
unsafe fn reset_sigpipe() {
- assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
+ assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
}
#[cfg(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia"))]
unsafe fn reset_sigpipe() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use cmp;
use io;
use libc::{self, c_int};
use mem;
-use ptr;
use sys::{cvt, cvt_r};
use sys::fd::FileDesc;
p1.set_nonblocking(true)?;
p2.set_nonblocking(true)?;
- let max = cmp::max(p1.raw(), p2.raw());
+ let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
+ fds[0].fd = p1.raw();
+ fds[0].events = libc::POLLIN;
+ fds[1].fd = p2.raw();
+ fds[1].events = libc::POLLIN;
loop {
- // wait for either pipe to become readable using `select`
- cvt_r(|| unsafe {
- let mut read: libc::fd_set = mem::zeroed();
- libc::FD_SET(p1.raw(), &mut read);
- libc::FD_SET(p2.raw(), &mut read);
- libc::select(max + 1, &mut read, ptr::null_mut(), ptr::null_mut(),
- ptr::null_mut())
- })?;
+ // wait for either pipe to become readable using `poll`
+ cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;
// Read as much as we can from each pipe, ignoring EWOULDBLOCK or
// EAGAIN. If we hit EOF, then this will happen because the underlying
}
}
};
- if read(&p1, v1)? {
+ if fds[0].revents != 0 && read(&p1, v1)? {
p2.set_nonblocking(false)?;
return p2.read_to_end(v2).map(|_| ());
}
- if read(&p2, v2)? {
+ if fds[1].revents != 0 && read(&p2, v2)? {
p1.set_nonblocking(false)?;
return p1.read_to_end(v1).map(|_| ());
}
//! [`Err`]: ../../std/result/enum.Result.html#variant.Err
//! [`panic!`]: ../../std/macro.panic.html
//! [`Builder`]: ../../std/thread/struct.Builder.html
-//! [`thread::current`]: ../../std/thread/fn.spawn.html
+//! [`thread::current`]: ../../std/thread/fn.current.html
//! [`Thread`]: ../../std/thread/struct.Thread.html
//! [`park`]: ../../std/thread/fn.park.html
//! [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark
return true;
}
- match attr.parse_list(cx.parse_sess, |parser| parser.parse_path(PathStyle::Mod)) {
+ match attr.parse_list(cx.parse_sess,
+ |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
Ok(ref traits) if traits.is_empty() => {
cx.span_warn(attr.span, "empty trait list in `derive`");
false
// Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
(active, generic_param_attrs, "1.11.0", Some(34761)),
- // The #![windows_subsystem] attribute
- (active, windows_subsystem, "1.14.0", Some(37499)),
-
// Allows #[link(..., cfg(..))]
(active, link_cfg, "1.14.0", Some(37406)),
(accepted, static_recursion, "1.17.0", Some(29719)),
// pub(restricted) visibilities (RFC 1422)
(accepted, pub_restricted, "1.17.0", Some(32409)),
-
+ // The #![windows_subsystem] attribute
+ (accepted, windows_subsystem, "1.18.0", Some(37499)),
);
// If you change this, please modify src/doc/unstable-book as well. You must
// move that documentation into the relevant place in the other docs, and
"unboxed_closures are still evolving",
cfg_fn!(unboxed_closures))),
- ("windows_subsystem", Whitelisted, Gated(Stability::Unstable,
- "windows_subsystem",
- "the windows subsystem attribute \
- is currently unstable",
- cfg_fn!(windows_subsystem))),
+ ("windows_subsystem", Whitelisted, Ungated),
("proc_macro_attribute", Normal, Gated(Stability::Unstable,
"proc_macro",
})
}
+ /// Like `parse_path`, but also supports parsing `Word` meta items into paths for back-compat.
+ /// This is used when parsing derive macro paths in `#[derive]` attributes.
+ pub fn parse_path_allowing_meta(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
+ let meta_ident = match self.token {
+ token::Interpolated(ref nt) => match **nt {
+ token::NtMeta(ref meta) => match meta.node {
+ ast::MetaItemKind::Word => Some(ast::Ident::with_empty_ctxt(meta.name)),
+ _ => None,
+ },
+ _ => None,
+ },
+ _ => None,
+ };
+ if let Some(ident) = meta_ident {
+ self.bump();
+ return Ok(ast::Path::from_ident(self.prev_span, ident));
+ }
+ self.parse_path(mode)
+ }
+
/// Examples:
/// - `a::b<T,U>::c<V,W>`
/// - `a::b<T,U>::c(V) -> W`
})
}
- fn complain_if_pub_macro(&mut self, visa: &Visibility, span: Span) {
- match *visa {
- Visibility::Inherited => (),
+ fn complain_if_pub_macro(&mut self, vis: &Visibility, sp: Span) {
+ if let Err(mut err) = self.complain_if_pub_macro_diag(vis, sp) {
+ err.emit();
+ }
+ }
+
+ fn complain_if_pub_macro_diag(&mut self, vis: &Visibility, sp: Span) -> PResult<'a, ()> {
+ match *vis {
+ Visibility::Inherited => Ok(()),
_ => {
let is_macro_rules: bool = match self.token {
token::Ident(sid) => sid.name == Symbol::intern("macro_rules"),
_ => false,
};
if is_macro_rules {
- self.diagnostic().struct_span_err(span, "can't qualify macro_rules \
- invocation with `pub`")
- .help("did you mean #[macro_export]?")
- .emit();
+ let mut err = self.diagnostic()
+ .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`");
+ err.help("did you mean #[macro_export]?");
+ Err(err)
} else {
- self.diagnostic().struct_span_err(span, "can't qualify macro \
- invocation with `pub`")
- .help("try adjusting the macro to put `pub` \
- inside the invocation")
- .emit();
+ let mut err = self.diagnostic()
+ .struct_span_err(sp, "can't qualify macro invocation with `pub`");
+ err.help("try adjusting the macro to put `pub` inside the invocation");
+ Err(err)
}
}
}
-> PResult<'a, (Ident, Vec<ast::Attribute>, ast::ImplItemKind)> {
// code copied from parse_macro_use_or_failure... abstraction!
if self.token.is_path_start() {
- // method macro.
+ // Method macro.
let prev_span = self.prev_span;
- self.complain_if_pub_macro(&vis, prev_span);
+ // Before complaining about trying to set a macro as `pub`,
+ // check if `!` comes after the path.
+ let err = self.complain_if_pub_macro_diag(&vis, prev_span);
let lo = self.span;
let pth = self.parse_path(PathStyle::Mod)?;
- self.expect(&token::Not)?;
+ let bang_err = self.expect(&token::Not);
+ if let Err(mut err) = err {
+ if let Err(mut bang_err) = bang_err {
+ // Given this code `pub path(`, it seems like this is not setting the
+ // visibility of a macro invocation, but rather a mistyped method declaration.
+ // Create a diagnostic pointing out that `fn` is missing.
+ //
+ // x | pub path(&self) {
+ // | ^ missing `fn` for method declaration
+
+ err.cancel();
+ bang_err.cancel();
+ // pub path(
+ // ^^ `sp` below will point to this
+ let sp = prev_span.between(self.prev_span);
+ err = self.diagnostic()
+ .struct_span_err(sp, "missing `fn` for method declaration");
+ err.span_label(sp, &"missing `fn`");
+ }
+ return Err(err);
+ }
// eat a matched-delimiter token tree:
let (delim, tts) = self.expect_delimited_token_tree()?;
use serialize::{Encodable, Decodable, Encoder, Decoder};
+use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
+ HashStable};
/// An owned smart pointer.
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct P<T: ?Sized> {
}))
}
}
+
+impl<CTX, T> HashStable<CTX> for P<T>
+ where T: ?Sized + HashStable<CTX>
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ (**self).hash_stable(hcx, hasher);
+ }
+}
use std::ops::Deref;
use std::rc::Rc;
+use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
+ HashStable};
+
#[derive(Clone)]
pub struct RcSlice<T> {
data: Rc<Box<[T]>>,
fmt::Debug::fmt(self.deref(), f)
}
}
+
+impl<CTX, T> HashStable<CTX> for RcSlice<T>
+ where T: HashStable<CTX>
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ (**self).hash_stable(hcx, hasher);
+ }
+}
Span { hi: end.hi, ..self }
}
}
+
+ pub fn between(self, end: Span) -> Span {
+ Span {
+ lo: self.hi,
+ hi: end.lo,
+ ctxt: if end.ctxt == SyntaxContext::empty() {
+ end.ctxt
+ } else {
+ self.ctxt
+ }
+ }
+ }
+
+ pub fn until(self, end: Span) -> Span {
+ Span {
+ lo: self.lo,
+ hi: end.lo,
+ ctxt: if end.ctxt == SyntaxContext::empty() {
+ end.ctxt
+ } else {
+ self.ctxt
+ }
+ }
+ }
}
#[derive(Clone, Debug)]
///
/// Note: this method sacrifices performance at the altar of accuracy
/// Depends on IEEE-754 arithmetic guarantees. See proof of correctness at:
- /// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates"]
- /// (http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps)
+ /// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric
+ /// Predicates"][paper]
+ ///
+ /// [paper]: http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps
fn sum(&self) -> f64;
/// Minimum value of the samples.
} else if target.contains("dragonfly") {
println!("cargo:rustc-link-lib=gcc_pic");
} else if target.contains("windows-gnu") {
- println!("cargo:rustc-link-lib=gcc_eh");
+ println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
+ println!("cargo:rustc-link-lib=static-nobundle=pthread");
} else if target.contains("fuchsia") {
println!("cargo:rustc-link-lib=unwind");
}
#![feature(cfg_target_vendor)]
#![feature(staged_api)]
#![feature(unwind_attributes)]
+#![feature(static_nobundle)]
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
--- /dev/null
+// Copyright 2017 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-msvc
+
+// compile-flags: -O -C no-prepopulate-passes
+
+#![crate_type="lib"]
+
+struct S;
+
+impl Drop for S {
+ fn drop(&mut self) {
+ }
+}
+
+fn might_unwind() {
+}
+
+// CHECK-LABEL: @test
+#[no_mangle]
+pub fn test() {
+ let _s = S;
+ // Check that the personality slot alloca gets a lifetime start in each cleanup block, not just
+ // in the first one.
+ // CHECK-LABEL: cleanup:
+ // CHECK: bitcast{{.*}}personalityslot
+ // CHECK-NEXT: call void @llvm.lifetime.start
+ // CHECK-LABEL: cleanup1:
+ // CHECK: bitcast{{.*}}personalityslot
+ // CHECK-NEXT: call void @llvm.lifetime.start
+ might_unwind();
+ might_unwind();
+}
+++ /dev/null
-// Copyright 2016 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.
-
-#![allow(dead_code)]
-
-trait C {}
-impl C { fn f() {} } //~ ERROR duplicate definitions with name `f`
-impl C { fn f() {} }
-fn main() { }
+++ /dev/null
-// Copyright 2016 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.
-
-// Test that you cannot define items with the same name in overlapping inherent
-// impl blocks.
-
-#![allow(unused)]
-
-struct Foo;
-
-impl Foo {
- fn id() {} //~ ERROR duplicate definitions
-}
-
-impl Foo {
- fn id() {}
-}
-
-struct Bar<T>(T);
-
-impl<T> Bar<T> {
- fn bar(&self) {} //~ ERROR duplicate definitions
-}
-
-impl Bar<u32> {
- fn bar(&self) {}
-}
-
-struct Baz<T>(T);
-
-impl<T: Copy> Baz<T> {
- fn baz(&self) {} //~ ERROR duplicate definitions
-}
-
-impl<T> Baz<Vec<T>> {
- fn baz(&self) {}
-}
-
-fn main() {}
+++ /dev/null
-// Copyright 2016 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.
-
-// gate-test-windows_subsystem
-
-#![windows_subsystem = "console"]
-//~^ ERROR: the windows subsystem attribute is currently unstable
-
-fn main() {}
// error-pattern: invalid windows subsystem `wrong`, only `windows` and `console` are allowed
-#![feature(windows_subsystem)]
#![windows_subsystem = "wrong"]
fn main() {}
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) foo.rs --emit=asm,llvm-ir -o $(TMPDIR)/out 2>&1
+ rm $(TMPDIR)/out.ll $(TMPDIR)/out.s
+ $(RUSTC) foo.rs --emit=asm,llvm-ir -o $(TMPDIR)/out2.ext 2>&1
+ rm $(TMPDIR)/out2.ll $(TMPDIR)/out2.s
--- /dev/null
+// Copyright 2014 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.
+
+fn main() {}
print!("{0} + {} = {}", x, y);
print!("x is {}, y is {1}, name is {n}", x, y, n = name);
}
+
+extern {
+ static EXTERN_FOO: u8;
+ fn extern_foo(a: u8, b: i32) -> String;
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(windows_subsystem)]
#![windows_subsystem = "console"]
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(windows_subsystem)]
#![windows_subsystem = "windows"]
fn main() {}
#![deny(const_err)]
const X: *const u8 = b"" as _;
+const Y: bool = 'A' == 'B';
+const Z: char = 'A';
+const W: bool = Z <= 'B';
+
fn main() {
let _ = ((-1 as i8) << 8 - 1) as f32;
--- /dev/null
+// Copyright 2017 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.
+
+macro_rules! m {
+ ($i:meta) => {
+ #[derive($i)]
+ struct S;
+ }
+}
+
+m!(Clone);
+
+fn main() {}
--- /dev/null
+// Copyright 2017 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.
+
+#![crate_name = "foo"]
+
+// ignore-tidy-linelength
+
+// @has foo/fn.f.html
+// @has - "<pre class='rust fn'>pub fn f()</pre><div class='docblock'><ol><li>list<ol><li>fooooo</li><li>x</li></ol></li><li>foo</li></ol>"
+/// 1. list
+/// 1. fooooo
+/// 2. x
+/// 2. foo
+pub fn f() {}
+
+// @has foo/fn.foo2.html
+// @has - "<pre class='rust fn'>pub fn foo2()</pre><div class='docblock'><ul><li>normal list<ul><li><p>sub list</p></li><li><p>new elem still same elem</p><p>and again same elem!</p></li></ul></li><li>new big elem</li></ul>"
+/// * normal list
+/// * sub list
+/// * new elem
+/// still same elem
+///
+/// and again same elem!
+/// * new big elem
+pub fn foo2() {}
\ No newline at end of file
--- /dev/null
+// Copyright 2016 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.
+
+#![allow(dead_code)]
+
+trait C {}
+impl C { fn f() {} }
+impl C { fn f() {} }
+fn main() { }
--- /dev/null
+error[E0592]: duplicate definitions with name `f`
+ --> $DIR/coherence-overlapping-inherent-impl-trait.rs:14:10
+ |
+14 | impl C { fn f() {} }
+ | ^^^^^^^^^ duplicate definitions for `f`
+15 | impl C { fn f() {} }
+ | --------- other definition for `f`
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 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.
+
+// Test that you cannot define items with the same name in overlapping inherent
+// impl blocks.
+
+#![allow(unused)]
+
+struct Foo;
+
+impl Foo {
+ fn id() {}
+}
+
+impl Foo {
+ fn id() {}
+}
+
+struct Bar<T>(T);
+
+impl<T> Bar<T> {
+ fn bar(&self) {}
+}
+
+impl Bar<u32> {
+ fn bar(&self) {}
+}
+
+struct Baz<T>(T);
+
+impl<T: Copy> Baz<T> {
+ fn baz(&self) {}
+}
+
+impl<T> Baz<Vec<T>> {
+ fn baz(&self) {}
+}
+
+fn main() {}
--- /dev/null
+error[E0592]: duplicate definitions with name `id`
+ --> $DIR/overlapping_inherent_impls.rs:19:5
+ |
+19 | fn id() {}
+ | ^^^^^^^^^^ duplicate definitions for `id`
+...
+23 | fn id() {}
+ | ---------- other definition for `id`
+
+error[E0592]: duplicate definitions with name `bar`
+ --> $DIR/overlapping_inherent_impls.rs:29:5
+ |
+29 | fn bar(&self) {}
+ | ^^^^^^^^^^^^^^^^ duplicate definitions for `bar`
+...
+33 | fn bar(&self) {}
+ | ---------------- other definition for `bar`
+
+error[E0592]: duplicate definitions with name `baz`
+ --> $DIR/overlapping_inherent_impls.rs:39:5
+ |
+39 | fn baz(&self) {}
+ | ^^^^^^^^^^^^^^^^ duplicate definitions for `baz`
+...
+43 | fn baz(&self) {}
+ | ---------------- other definition for `baz`
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+// Copyright 2017 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.
+
+struct S;
+
+impl S {
+ pub hello_method(&self) {
+ println!("Hello");
+ }
+}
+
+fn main() {
+ S.hello_method();
+}
--- /dev/null
+error: missing `fn` for method declaration
+ --> $DIR/issue-40006.rs:14:8
+ |
+14 | pub hello_method(&self) {
+ | ^ missing `fn`
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2017 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.
+
+pub mod animal {
+ pub struct Dog {
+ pub age: usize,
+ dog_age: usize,
+ }
+
+ impl Dog {
+ pub fn new(age: usize) -> Dog {
+ Dog { age: age, dog_age: age * 7 }
+ }
+ }
+}
+
+fn main() {
+ let dog = animal::Dog::new(3);
+ let dog_age = dog.dog_age();
+ //let dog_age = dog.dog_age;
+ println!("{}", dog_age);
+}
--- /dev/null
+error: no method named `dog_age` found for type `animal::Dog` in the current scope
+ --> $DIR/private-field.rs:26:23
+ |
+26 | let dog_age = dog.dog_age();
+ | ^^^^^^^ private field, not a method
+
+error: aborting due to previous error
+
"src/libtest", // Probably should defer to unstable std::sys APIs
// std testing crates, ok for now at least
- "src/libcoretest",
+ "src/libcore/tests",
// non-std crates
"src/test",