From 85707398809f8b56afc471f228bd4d0137ce0a32 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 10 Mar 2015 23:12:55 -0500 Subject: [PATCH 01/15] allow inherent implementations on primitives --- src/librustc/middle/lang_items.rs | 18 +++ src/librustc/middle/ty.rs | 23 +++ src/librustc_typeck/check/method/probe.rs | 76 ++++++++++ src/librustc_typeck/coherence/orphan.rs | 137 ++++++++++++++++++ .../single-primitive-inherent-impl.rs | 24 +++ 5 files changed, 278 insertions(+) create mode 100644 src/test/compile-fail/single-primitive-inherent-impl.rs diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 3525d46a1f2f1..1ad4611dc9ee3 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -239,6 +239,24 @@ pub fn collect_language_items(krate: &ast::Crate, lets_do_this! { // Variant name, Name, Method name; + CharImplItem, "char", char_impl; + StrImplItem, "str", str_impl; + SliceImplItem, "slice", slice_impl; + ConstPtrImplItem, "const_ptr", const_ptr_impl; + MutPtrImplItem, "mut_ptr", mut_ptr_impl; + I8ImplItem, "i8", i8_impl; + I16ImplItem, "i16", i16_impl; + I32ImplItem, "i32", i32_impl; + I64ImplItem, "i64", i64_impl; + IsizeImplItem, "isize", isize_impl; + U8ImplItem, "u8", u8_impl; + U16ImplItem, "u16", u16_impl; + U32ImplItem, "u32", u32_impl; + U64ImplItem, "u64", u64_impl; + UsizeImplItem, "usize", usize_impl; + F32ImplItem, "f32", f32_impl; + F64ImplItem, "f64", f64_impl; + SendTraitLangItem, "send", send_trait; SizedTraitLangItem, "sized", sized_trait; CopyTraitLangItem, "copy", copy_trait; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8705e56b09425..c3e1879fca8ea 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -788,6 +788,9 @@ pub struct ctxt<'tcx> { /// is used for lazy resolution of traits. pub populated_external_traits: RefCell, + /// The set of external primitive inherent implementations that have been read. + pub populated_external_primitive_impls: RefCell, + /// Borrows pub upvar_capture_map: RefCell, @@ -2599,6 +2602,7 @@ pub fn mk_ctxt<'tcx>(s: Session, used_mut_nodes: RefCell::new(NodeSet()), populated_external_types: RefCell::new(DefIdSet()), populated_external_traits: RefCell::new(DefIdSet()), + populated_external_primitive_impls: RefCell::new(DefIdSet()), upvar_capture_map: RefCell::new(FnvHashMap()), extern_const_statics: RefCell::new(DefIdMap()), extern_const_variants: RefCell::new(DefIdMap()), @@ -5988,6 +5992,25 @@ pub fn record_trait_implementation(tcx: &ctxt, tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id)))); } +/// Load primitive inherent implementations if necessary +pub fn populate_implementations_for_primitive_if_necessary(tcx: &ctxt, lang_def_id: ast::DefId) { + if lang_def_id.krate == LOCAL_CRATE { + return + } + if tcx.populated_external_primitive_impls.borrow().contains(&lang_def_id) { + return + } + + debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}", lang_def_id); + + let impl_items = csearch::get_impl_items(&tcx.sess.cstore, lang_def_id); + + // Store the implementation info. + tcx.impl_items.borrow_mut().insert(lang_def_id, impl_items); + + tcx.populated_external_primitive_impls.borrow_mut().insert(lang_def_id); +} + /// Populates the type context with all the implementations for the given type /// if necessary. pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 718804d317fb0..1f7cc3bb64782 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -289,11 +289,87 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { ty::ty_param(p) => { self.assemble_inherent_candidates_from_param(self_ty, p); } + ty::ty_char => { + let lang_def_id = self.tcx().lang_items.char_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_str => { + let lang_def_id = self.tcx().lang_items.str_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_vec(_, None) => { + let lang_def_id = self.tcx().lang_items.slice_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => { + let lang_def_id = self.tcx().lang_items.const_ptr_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutMutable }) => { + let lang_def_id = self.tcx().lang_items.mut_ptr_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI8) => { + let lang_def_id = self.tcx().lang_items.i8_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI16) => { + let lang_def_id = self.tcx().lang_items.i16_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI32) => { + let lang_def_id = self.tcx().lang_items.i32_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI64) => { + let lang_def_id = self.tcx().lang_items.i64_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyIs(_)) => { + let lang_def_id = self.tcx().lang_items.isize_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU8) => { + let lang_def_id = self.tcx().lang_items.u8_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU16) => { + let lang_def_id = self.tcx().lang_items.u16_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU32) => { + let lang_def_id = self.tcx().lang_items.u32_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU64) => { + let lang_def_id = self.tcx().lang_items.u64_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyUs(_)) => { + let lang_def_id = self.tcx().lang_items.usize_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_float(ast::TyF32) => { + let lang_def_id = self.tcx().lang_items.f32_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_float(ast::TyF64) => { + let lang_def_id = self.tcx().lang_items.f64_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } _ => { } } } + fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option) { + if let Some(impl_def_id) = lang_def_id { + ty::populate_implementations_for_primitive_if_necessary(self.tcx(), impl_def_id); + + self.assemble_inherent_impl_probe(impl_def_id); + } + } + fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: ast::DefId) { // Read the inherent implementation candidates for this type from the // metadata if necessary. diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 5dfe80cfcb213..ab694d26b155c 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -16,6 +16,7 @@ use middle::ty; use syntax::ast::{Item, ItemImpl}; use syntax::ast; use syntax::ast_util; +use syntax::codemap::Span; use syntax::visit; use util::ppaux::{Repr, UserString}; @@ -38,6 +39,23 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { } } + fn check_primitive_impl(&self, + impl_def_id: ast::DefId, + lang_def_id: Option, + lang: &str, + ty: &str, + span: Span) { + match lang_def_id { + Some(lang_def_id) if lang_def_id == impl_def_id => { /* OK */ }, + _ => { + self.tcx.sess.span_err( + span, + &format!("only a single inherent implementation marked with `#[lang = \"{}\"]` \ + is allowed for the `{}` primitive", lang, ty)); + } + } + } + /// Checks exactly one impl for orphan rules and other such /// restrictions. In this fn, it can happen that multiple errors /// apply to a specific impl, so just return after reporting one @@ -62,6 +80,125 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { ty::ty_uniq(..) => { self.check_def_id(item, self.tcx.lang_items.owned_box().unwrap()); } + ty::ty_char => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.char_impl(), + "char", + "char", + item.span); + } + ty::ty_str => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.str_impl(), + "str", + "str", + item.span); + } + ty::ty_vec(_, None) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.slice_impl(), + "slice", + "[T]", + item.span); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.const_ptr_impl(), + "const_ptr", + "*const T", + item.span); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutMutable }) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.mut_ptr_impl(), + "mut_ptr", + "*mut T", + item.span); + } + ty::ty_int(ast::TyI8) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i8_impl(), + "i8", + "i8", + item.span); + } + ty::ty_int(ast::TyI16) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i16_impl(), + "i16", + "i16", + item.span); + } + ty::ty_int(ast::TyI32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i32_impl(), + "i32", + "i32", + item.span); + } + ty::ty_int(ast::TyI64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i64_impl(), + "i64", + "i64", + item.span); + } + ty::ty_int(ast::TyIs(_)) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.isize_impl(), + "isize", + "isize", + item.span); + } + ty::ty_uint(ast::TyU8) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u8_impl(), + "u8", + "u8", + item.span); + } + ty::ty_uint(ast::TyU16) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u16_impl(), + "u16", + "u16", + item.span); + } + ty::ty_uint(ast::TyU32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u32_impl(), + "u32", + "u32", + item.span); + } + ty::ty_uint(ast::TyU64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u64_impl(), + "u64", + "u64", + item.span); + } + ty::ty_uint(ast::TyUs(_)) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.usize_impl(), + "usize", + "usize", + item.span); + } + ty::ty_float(ast::TyF32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.f32_impl(), + "f32", + "f32", + item.span); + } + ty::ty_float(ast::TyF64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.f64_impl(), + "f64", + "f64", + item.span); + } _ => { span_err!(self.tcx.sess, item.span, E0118, "no base type found for inherent implementation; \ diff --git a/src/test/compile-fail/single-primitive-inherent-impl.rs b/src/test/compile-fail/single-primitive-inherent-impl.rs new file mode 100644 index 0000000000000..b2cfcfab78b37 --- /dev/null +++ b/src/test/compile-fail/single-primitive-inherent-impl.rs @@ -0,0 +1,24 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +#![crate_type = "lib"] +#![feature(lang_items)] +#![feature(no_std)] +#![no_std] + +// OK +#[lang = "char"] +impl char {} + +impl char { +//~^ error: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive +} From b2f37554bf9f2b55fa6ba6ba8e8eaf1826301b4e Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 10 Mar 2015 23:13:16 -0500 Subject: [PATCH 02/15] impl char --- src/libcollections/lib.rs | 1 - src/libstd/num/strconv.rs | 3 + src/libstd/old_io/mod.rs | 1 + src/libstd/old_path/windows.rs | 1 + src/libstd/path.rs | 1 + src/libstd/prelude/v1.rs | 1 + src/libunicode/char.rs | 372 +++++++++++++++++++++++++++++++++ src/libunicode/lib.rs | 1 + src/libunicode/u_str.rs | 1 + 9 files changed, 381 insertions(+), 1 deletion(-) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index e90186d63b4dc..dd23bcbaf81b9 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -166,7 +166,6 @@ mod prelude { // from other crates. pub use alloc::boxed::Box; - pub use unicode::char::CharExt; // from collections. pub use borrow::IntoCow; diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 5fdd42dbc7a83..fa24e9fd5afc5 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -16,7 +16,10 @@ use self::ExponentFormat::*; use self::SignificantDigits::*; use self::SignFormat::*; +#[cfg(stage0)] use char::{self, CharExt}; +#[cfg(not(stage0))] +use char; use num::{self, Int, Float, ToPrimitive}; use num::FpCategory as Fp; use ops::FnMut; diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index 332b941bcc0fb..711faa98bd92e 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -251,6 +251,7 @@ pub use self::FileMode::*; pub use self::FileAccess::*; pub use self::IoErrorKind::*; +#[cfg(stage0)] use char::CharExt; use default::Default; use error::Error; diff --git a/src/libstd/old_path/windows.rs b/src/libstd/old_path/windows.rs index 838710b1aec8e..1387d531001be 100644 --- a/src/libstd/old_path/windows.rs +++ b/src/libstd/old_path/windows.rs @@ -15,6 +15,7 @@ use self::PathPrefix::*; use ascii::AsciiExt; +#[cfg(stage0)] use char::CharExt; use clone::Clone; use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd}; diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 2159e30074426..29c779df4d275 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -159,6 +159,7 @@ mod platform { use core::prelude::*; use ascii::*; + #[cfg(stage0)] use char::CharExt as UnicodeCharExt; use super::{os_str_as_u8_slice, u8_slice_as_os_str, Prefix}; use ffi::OsStr; diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 31aac333859cd..b244f78585231 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -25,6 +25,7 @@ // Reexported types and traits #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use boxed::Box; +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use char::CharExt; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libunicode/char.rs b/src/libunicode/char.rs index bcc2820e381ac..56bc0389b7465 100644 --- a/src/libunicode/char.rs +++ b/src/libunicode/char.rs @@ -41,6 +41,7 @@ pub use normalize::{decompose_canonical, decompose_compatible, compose}; pub use tables::normalization::canonical_combining_class; pub use tables::UNICODE_VERSION; +#[cfg(stage0)] /// Functionality for manipulating `char`. #[stable(feature = "rust1", since = "1.0.0")] pub trait CharExt { @@ -374,6 +375,7 @@ pub trait CharExt { fn width(self, is_cjk: bool) -> Option; } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl CharExt for char { fn is_digit(self, radix: u32) -> bool { C::is_digit(self, radix) } @@ -467,3 +469,373 @@ impl Iterator for ToUppercase { type Item = char; fn next(&mut self) -> Option { self.0.take() } } + +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +#[lang = "char"] +impl char { + /// Checks if a `char` parses as a numeric digit in the given radix. + /// + /// Compared to `is_numeric()`, this function only recognizes the characters + /// `0-9`, `a-z` and `A-Z`. + /// + /// # Return value + /// + /// Returns `true` if `c` is a valid digit under `radix`, and `false` + /// otherwise. + /// + /// # Panics + /// + /// Panics if given a radix > 36. + /// + /// # Examples + /// + /// ``` + /// let c = '1'; + /// + /// assert!(c.is_digit(10)); + /// + /// assert!('f'.is_digit(16)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_digit(self, radix: u32) -> bool { C::is_digit(self, radix) } + + /// Converts a character to the corresponding digit. + /// + /// # Return value + /// + /// If `c` is between '0' and '9', the corresponding value between 0 and + /// 9. If `c` is 'a' or 'A', 10. If `c` is 'b' or 'B', 11, etc. Returns + /// none if the character does not refer to a digit in the given radix. + /// + /// # Panics + /// + /// Panics if given a radix outside the range [0..36]. + /// + /// # Examples + /// + /// ``` + /// let c = '1'; + /// + /// assert_eq!(c.to_digit(10), Some(1)); + /// + /// assert_eq!('f'.to_digit(16), Some(15)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_digit(self, radix: u32) -> Option { C::to_digit(self, radix) } + + /// Returns an iterator that yields the hexadecimal Unicode escape of a + /// character, as `char`s. + /// + /// All characters are escaped with Rust syntax of the form `\\u{NNNN}` + /// where `NNNN` is the shortest hexadecimal representation of the code + /// point. + /// + /// # Examples + /// + /// ``` + /// for i in '❤'.escape_unicode() { + /// println!("{}", i); + /// } + /// ``` + /// + /// This prints: + /// + /// ```text + /// \ + /// u + /// { + /// 2 + /// 7 + /// 6 + /// 4 + /// } + /// ``` + /// + /// Collecting into a `String`: + /// + /// ``` + /// let heart: String = '❤'.escape_unicode().collect(); + /// + /// assert_eq!(heart, r"\u{2764}"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn escape_unicode(self) -> EscapeUnicode { C::escape_unicode(self) } + + /// Returns an iterator that yields the 'default' ASCII and + /// C++11-like literal escape of a character, as `char`s. + /// + /// The default is chosen with a bias toward producing literals that are + /// legal in a variety of languages, including C++11 and similar C-family + /// languages. The exact rules are: + /// + /// * Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively. + /// * Single-quote, double-quote and backslash chars are backslash- + /// escaped. + /// * Any other chars in the range [0x20,0x7e] are not escaped. + /// * Any other chars are given hex Unicode escapes; see `escape_unicode`. + /// + /// # Examples + /// + /// ``` + /// for i in '"'.escape_default() { + /// println!("{}", i); + /// } + /// ``` + /// + /// This prints: + /// + /// ```text + /// \ + /// " + /// ``` + /// + /// Collecting into a `String`: + /// + /// ``` + /// let quote: String = '"'.escape_default().collect(); + /// + /// assert_eq!(quote, "\\\""); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn escape_default(self) -> EscapeDefault { C::escape_default(self) } + + /// Returns the number of bytes this character would need if encoded in + /// UTF-8. + /// + /// # Examples + /// + /// ``` + /// let n = 'ß'.len_utf8(); + /// + /// assert_eq!(n, 2); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn len_utf8(self) -> usize { C::len_utf8(self) } + + /// Returns the number of 16-bit code units this character would need if + /// encoded in UTF-16. + /// + /// # Examples + /// + /// ``` + /// let n = 'ß'.len_utf16(); + /// + /// assert_eq!(n, 1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn len_utf16(self) -> usize { C::len_utf16(self) } + + /// Encodes this character as UTF-8 into the provided byte buffer, and then + /// returns the number of bytes written. + /// + /// If the buffer is not large enough, nothing will be written into it and a + /// `None` will be returned. A buffer of length four is large enough to + /// encode any `char`. + /// + /// # Examples + /// + /// In both of these examples, 'ß' takes two bytes to encode. + /// + /// ``` + /// let mut b = [0; 2]; + /// + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, Some(2)); + /// ``` + /// + /// A buffer that's too small: + /// + /// ``` + /// let mut b = [0; 1]; + /// + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, None); + /// ``` + #[unstable(feature = "unicode", + reason = "pending decision about Iterator/Writer/Reader")] + pub fn encode_utf8(self, dst: &mut [u8]) -> Option { C::encode_utf8(self, dst) } + + /// Encodes this character as UTF-16 into the provided `u16` buffer, and + /// then returns the number of `u16`s written. + /// + /// If the buffer is not large enough, nothing will be written into it and a + /// `None` will be returned. A buffer of length 2 is large enough to encode + /// any `char`. + /// + /// # Examples + /// + /// In both of these examples, 'ß' takes one `u16` to encode. + /// + /// ``` + /// let mut b = [0; 1]; + /// + /// let result = 'ß'.encode_utf16(&mut b); + /// + /// assert_eq!(result, Some(1)); + /// ``` + /// + /// A buffer that's too small: + /// + /// ``` + /// let mut b = [0; 0]; + /// + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, None); + /// ``` + #[unstable(feature = "unicode", + reason = "pending decision about Iterator/Writer/Reader")] + pub fn encode_utf16(self, dst: &mut [u16]) -> Option { C::encode_utf16(self, dst) } + + /// Returns whether the specified character is considered a Unicode + /// alphabetic code point. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_alphabetic(self) -> bool { + match self { + 'a' ... 'z' | 'A' ... 'Z' => true, + c if c > '\x7f' => derived_property::Alphabetic(c), + _ => false + } + } + + /// Returns whether the specified character satisfies the 'XID_Start' + /// Unicode property. + /// + /// 'XID_Start' is a Unicode Derived Property specified in + /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), + /// mostly similar to ID_Start but modified for closure under NFKx. + #[unstable(feature = "unicode", + reason = "mainly needed for compiler internals")] + pub fn is_xid_start(self) -> bool { derived_property::XID_Start(self) } + + /// Returns whether the specified `char` satisfies the 'XID_Continue' + /// Unicode property. + /// + /// 'XID_Continue' is a Unicode Derived Property specified in + /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), + /// mostly similar to 'ID_Continue' but modified for closure under NFKx. + #[unstable(feature = "unicode", + reason = "mainly needed for compiler internals")] + pub fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) } + + /// Indicates whether a character is in lowercase. + /// + /// This is defined according to the terms of the Unicode Derived Core + /// Property `Lowercase`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_lowercase(self) -> bool { + match self { + 'a' ... 'z' => true, + c if c > '\x7f' => derived_property::Lowercase(c), + _ => false + } + } + + /// Indicates whether a character is in uppercase. + /// + /// This is defined according to the terms of the Unicode Derived Core + /// Property `Uppercase`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_uppercase(self) -> bool { + match self { + 'A' ... 'Z' => true, + c if c > '\x7f' => derived_property::Uppercase(c), + _ => false + } + } + + /// Indicates whether a character is whitespace. + /// + /// Whitespace is defined in terms of the Unicode Property `White_Space`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_whitespace(self) -> bool { + match self { + ' ' | '\x09' ... '\x0d' => true, + c if c > '\x7f' => property::White_Space(c), + _ => false + } + } + + /// Indicates whether a character is alphanumeric. + /// + /// Alphanumericness is defined in terms of the Unicode General Categories + /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_alphanumeric(self) -> bool { + self.is_alphabetic() || self.is_numeric() + } + + /// Indicates whether a character is a control code point. + /// + /// Control code points are defined in terms of the Unicode General + /// Category `Cc`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_control(self) -> bool { general_category::Cc(self) } + + /// Indicates whether the character is numeric (Nd, Nl, or No). + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_numeric(self) -> bool { + match self { + '0' ... '9' => true, + c if c > '\x7f' => general_category::N(c), + _ => false + } + } + + /// Converts a character to its lowercase equivalent. + /// + /// The case-folding performed is the common or simple mapping. See + /// `to_uppercase()` for references and more information. + /// + /// # Return value + /// + /// Returns an iterator which yields the characters corresponding to the + /// lowercase equivalent of the character. If no conversion is possible then + /// the input character is returned. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_lowercase(self) -> ToLowercase { + ToLowercase(Some(conversions::to_lower(self))) + } + + /// Converts a character to its uppercase equivalent. + /// + /// The case-folding performed is the common or simple mapping: it maps + /// one Unicode codepoint to its uppercase equivalent according to the + /// Unicode database [1]. The additional [`SpecialCasing.txt`] is not yet + /// considered here, but the iterator returned will soon support this form + /// of case folding. + /// + /// A full reference can be found here [2]. + /// + /// # Return value + /// + /// Returns an iterator which yields the characters corresponding to the + /// uppercase equivalent of the character. If no conversion is possible then + /// the input character is returned. + /// + /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt + /// + /// [`SpecialCasing`.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt + /// + /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992 + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_uppercase(self) -> ToUppercase { + ToUppercase(Some(conversions::to_upper(self))) + } + + /// Returns this character's displayed width in columns, or `None` if it is a + /// control character other than `'\x00'`. + /// + /// `is_cjk` determines behavior for characters in the Ambiguous category: + /// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1. + /// In CJK contexts, `is_cjk` should be `true`, else it should be `false`. + /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) + /// recommends that these characters be treated as 1 column (i.e., + /// `is_cjk` = `false`) if the context cannot be reliably determined. + #[unstable(feature = "unicode", + reason = "needs expert opinion. is_cjk flag stands out as ugly")] + pub fn width(self, is_cjk: bool) -> Option { charwidth::width(self, is_cjk) } +} diff --git a/src/libunicode/lib.rs b/src/libunicode/lib.rs index fadf91f33bce8..a09c0cb3bd630 100644 --- a/src/libunicode/lib.rs +++ b/src/libunicode/lib.rs @@ -24,6 +24,7 @@ #![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "unicode"] #![unstable(feature = "unicode")] +#![feature(lang_items)] #![feature(staged_api)] #![staged_api] #![crate_type = "rlib"] diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 050d2adf0504b..6a80f3bc2c189 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -26,6 +26,7 @@ use core::num::Int; use core::slice; use core::str::Split; +#[cfg(stage0)] use char::CharExt as UCharExt; // conflicts with core::prelude::CharExt use tables::grapheme::GraphemeCat; From 5b118f5ecde796ad62fa349a045d7ad8129b711c Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 10 Mar 2015 23:13:24 -0500 Subject: [PATCH 03/15] impl str --- src/libcollections/lib.rs | 4 + src/libcollections/str.rs | 1136 +++++++++++++++++ src/libstd/ffi/c_str.rs | 1 + src/libstd/io/mod.rs | 3 + src/libstd/num/strconv.rs | 1 + src/libstd/old_io/mod.rs | 1 + src/libstd/old_io/net/ip.rs | 3 + src/libstd/old_io/process.rs | 2 +- src/libstd/old_io/stdio.rs | 1 + src/libstd/old_io/tempfile.rs | 1 + src/libstd/old_path/mod.rs | 1 + src/libstd/old_path/posix.rs | 5 +- src/libstd/old_path/windows.rs | 3 + src/libstd/os.rs | 3 + src/libstd/prelude/v1.rs | 4 + src/libstd/process.rs | 2 +- .../method-suggestion-no-duplication.rs | 1 - 17 files changed, 1168 insertions(+), 4 deletions(-) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index dd23bcbaf81b9..3a2fc17e1e985 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -27,6 +27,7 @@ #![feature(box_syntax)] #![feature(box_patterns)] #![feature(core)] +#![feature(lang_items)] #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(unicode)] @@ -162,7 +163,10 @@ mod prelude { // in core and collections (may differ). pub use slice::{AsSlice, SliceExt}; + #[cfg(stage0)] pub use str::{Str, StrExt}; + #[cfg(not(stage0))] + pub use str::Str; // from other crates. pub use alloc::boxed::Box; diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 31d7677d19eaf..b4e548e137e94 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -59,7 +59,9 @@ use self::DecompositionType::*; use core::clone::Clone; use core::iter::AdditiveIterator; use core::iter::{Iterator, IteratorExt, Extend}; +#[cfg(stage0)] use core::ops::Index; +#[cfg(stage0)] use core::ops::RangeFull; use core::option::Option::{self, Some, None}; use core::result::Result; @@ -415,6 +417,7 @@ Section: CowString Section: Trait implementations */ +#[cfg(stage0)] /// Any string that can be represented as a slice. #[stable(feature = "rust1", since = "1.0.0")] pub trait StrExt: Index { @@ -1539,6 +1542,7 @@ pub trait StrExt: Index { } } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl StrExt for str { fn slice(&self, begin: usize, end: usize) -> &str { @@ -1554,6 +1558,1138 @@ impl StrExt for str { } } +#[cfg(not(stage0))] +/// Any string that can be represented as a slice. +#[lang = "str"] +#[stable(feature = "rust1", since = "1.0.0")] +impl str { + /// Escapes each char in `s` with `char::escape_default`. + #[unstable(feature = "collections", + reason = "return type may change to be an iterator")] + pub fn escape_default(&self) -> String { + self.chars().flat_map(|c| c.escape_default()).collect() + } + + /// Escapes each char in `s` with `char::escape_unicode`. + #[unstable(feature = "collections", + reason = "return type may change to be an iterator")] + pub fn escape_unicode(&self) -> String { + self.chars().flat_map(|c| c.escape_unicode()).collect() + } + + /// Replaces all occurrences of one string with another. + /// + /// `replace` takes two arguments, a sub-`&str` to find in `self`, and a second `&str` to + /// replace it with. If the original `&str` isn't found, no change occurs. + /// + /// # Examples + /// + /// ``` + /// let s = "this is old"; + /// + /// assert_eq!(s.replace("old", "new"), "this is new"); + /// ``` + /// + /// When a `&str` isn't found: + /// + /// ``` + /// let s = "this is old"; + /// assert_eq!(s.replace("cookie monster", "little lamb"), s); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn replace(&self, from: &str, to: &str) -> String { + let mut result = String::new(); + let mut last_end = 0; + for (start, end) in self.match_indices(from) { + result.push_str(unsafe { self.slice_unchecked(last_end, start) }); + result.push_str(to); + last_end = end; + } + result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); + result + } + + /// Returns an iterator over the string in Unicode Normalization Form D + /// (canonical decomposition). + #[inline] + #[unstable(feature = "collections", + reason = "this functionality may be moved to libunicode")] + pub fn nfd_chars(&self) -> Decompositions { + Decompositions { + iter: self[..].chars(), + buffer: Vec::new(), + sorted: false, + kind: Canonical + } + } + + /// Returns an iterator over the string in Unicode Normalization Form KD + /// (compatibility decomposition). + #[inline] + #[unstable(feature = "collections", + reason = "this functionality may be moved to libunicode")] + pub fn nfkd_chars(&self) -> Decompositions { + Decompositions { + iter: self[..].chars(), + buffer: Vec::new(), + sorted: false, + kind: Compatible + } + } + + /// An Iterator over the string in Unicode Normalization Form C + /// (canonical decomposition followed by canonical composition). + #[inline] + #[unstable(feature = "collections", + reason = "this functionality may be moved to libunicode")] + pub fn nfc_chars(&self) -> Recompositions { + Recompositions { + iter: self.nfd_chars(), + state: Composing, + buffer: VecDeque::new(), + composee: None, + last_ccc: None + } + } + + /// An Iterator over the string in Unicode Normalization Form KC + /// (compatibility decomposition followed by canonical composition). + #[inline] + #[unstable(feature = "collections", + reason = "this functionality may be moved to libunicode")] + pub fn nfkc_chars(&self) -> Recompositions { + Recompositions { + iter: self.nfkd_chars(), + state: Composing, + buffer: VecDeque::new(), + composee: None, + last_ccc: None + } + } + + /// Returns `true` if `self` contains another `&str`. + /// + /// # Examples + /// + /// ``` + /// assert!("bananas".contains("nana")); + /// + /// assert!(!"bananas".contains("foobar")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + core_str::StrExt::contains(&self[..], pat) + } + + /// Returns `true` if `self` contains a `char`. + /// + /// # Examples + /// + /// ``` + /// assert!("hello".contains_char('e')); + /// + /// assert!(!"hello".contains_char('z')); + /// ``` + #[unstable(feature = "collections")] + #[deprecated(since = "1.0.0", reason = "use `contains()` with a char")] + pub fn contains_char<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + core_str::StrExt::contains_char(&self[..], pat) + } + + /// An iterator over the codepoints of `self`. + /// + /// # Examples + /// + /// ``` + /// let v: Vec = "abc åäö".chars().collect(); + /// + /// assert_eq!(v, ['a', 'b', 'c', ' ', 'å', 'ä', 'ö']); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn chars(&self) -> Chars { + core_str::StrExt::chars(&self[..]) + } + + /// An iterator over the bytes of `self`. + /// + /// # Examples + /// + /// ``` + /// let v: Vec = "bors".bytes().collect(); + /// + /// assert_eq!(v, b"bors".to_vec()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn bytes(&self) -> Bytes { + core_str::StrExt::bytes(&self[..]) + } + + /// An iterator over the characters of `self` and their byte offsets. + /// + /// # Examples + /// + /// ``` + /// let v: Vec<(usize, char)> = "abc".char_indices().collect(); + /// let b = vec![(0, 'a'), (1, 'b'), (2, 'c')]; + /// + /// assert_eq!(v, b); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn char_indices(&self) -> CharIndices { + core_str::StrExt::char_indices(&self[..]) + } + + /// An iterator over substrings of `self`, separated by characters + /// matched by a pattern. + /// + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); + /// + /// let v: Vec<&str> = "".split('X').collect(); + /// assert_eq!(v, [""]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); + /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { + core_str::StrExt::split(&self[..], pat) + } + + /// An iterator over substrings of `self`, separated by characters matched by a pattern, + /// restricted to splitting at most `count` times. + /// + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a little lambda"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect(); + /// assert_eq!(v, ["lion", "", "tigerXleopard"]); + /// + /// let v: Vec<&str> = "abcXdef".splitn(0, 'X').collect(); + /// assert_eq!(v, ["abcXdef"]); + /// + /// let v: Vec<&str> = "".splitn(1, 'X').collect(); + /// assert_eq!(v, [""]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["abc", "def2ghi"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> { + core_str::StrExt::splitn(&self[..], count, pat) + } + + /// An iterator over substrings of `self`, separated by characters + /// matched by a pattern. + /// + /// Equivalent to `split`, except that the trailing substring is skipped if empty. + /// + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); + /// assert_eq!(v, ["A", "B"]); + /// + /// let v: Vec<&str> = "A..B..".split_terminator('.').collect(); + /// assert_eq!(v, ["A", "", "B", ""]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi3".split_terminator(|c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { + core_str::StrExt::split_terminator(&self[..], pat) + } + + /// An iterator over substrings of `self`, separated by characters matched by a pattern, + /// starting from the end of the string. + /// + /// Restricted to splitting at most `count` times. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect(); + /// assert_eq!(v, ["lamb", "little", "Mary had a"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "lionX"]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["ghi", "abc1def"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> { + core_str::StrExt::rsplitn(&self[..], count, pat) + } + + /// An iterator over the start and end indices of the disjoint matches of a `&str` within + /// `self`. + /// + /// That is, each returned value `(start, end)` satisfies `self.slice(start, end) == sep`. For + /// matches of `sep` within `self` that overlap, only the indices corresponding to the first + /// match are returned. + /// + /// # Examples + /// + /// ``` + /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect(); + /// assert_eq!(v, [(0,3), (6,9), (12,15)]); + /// + /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect(); + /// assert_eq!(v, [(1,4), (4,7)]); + /// + /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect(); + /// assert_eq!(v, [(0, 3)]); // only the first `aba` + /// ``` + #[unstable(feature = "collections", + reason = "might have its iterator type changed")] + // NB: Right now MatchIndices yields `(usize, usize)`, + // but it would be more consistent and useful to return `(usize, &str)` + pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { + core_str::StrExt::match_indices(&self[..], pat) + } + + /// An iterator over the substrings of `self` separated by a `&str`. + /// + /// # Examples + /// + /// ``` + /// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect(); + /// assert_eq!(v, ["", "XXX", "YYY", ""]); + /// + /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect(); + /// assert_eq!(v, ["1", "", "2"]); + /// ``` + #[unstable(feature = "collections")] + #[deprecated(since = "1.0.0", reason = "use `split()` with a `&str`")] + #[allow(deprecated) /* for SplitStr */] + pub fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P> { + core_str::StrExt::split_str(&self[..], pat) + } + + /// An iterator over the lines of a string, separated by `\n`. + /// + /// This does not include the empty string after a trailing `\n`. + /// + /// # Examples + /// + /// ``` + /// let four_lines = "foo\nbar\n\nbaz"; + /// let v: Vec<&str> = four_lines.lines().collect(); + /// + /// assert_eq!(v, ["foo", "bar", "", "baz"]); + /// ``` + /// + /// Leaving off the trailing character: + /// + /// ``` + /// let four_lines = "foo\nbar\n\nbaz\n"; + /// let v: Vec<&str> = four_lines.lines().collect(); + /// + /// assert_eq!(v, ["foo", "bar", "", "baz"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn lines(&self) -> Lines { + core_str::StrExt::lines(&self[..]) + } + + /// An iterator over the lines of a string, separated by either `\n` or `\r\n`. + /// + /// As with `.lines()`, this does not include an empty trailing line. + /// + /// # Examples + /// + /// ``` + /// let four_lines = "foo\r\nbar\n\r\nbaz"; + /// let v: Vec<&str> = four_lines.lines_any().collect(); + /// + /// assert_eq!(v, ["foo", "bar", "", "baz"]); + /// ``` + /// + /// Leaving off the trailing character: + /// + /// ``` + /// let four_lines = "foo\r\nbar\n\r\nbaz\n"; + /// let v: Vec<&str> = four_lines.lines_any().collect(); + /// + /// assert_eq!(v, ["foo", "bar", "", "baz"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn lines_any(&self) -> LinesAny { + core_str::StrExt::lines_any(&self[..]) + } + + /// Deprecated: use `s[a .. b]` instead. + #[unstable(feature = "collections", + reason = "use slice notation [a..b] instead")] + #[deprecated(since = "1.0.0", reason = "use slice notation [a..b] instead")] + pub fn slice(&self, begin: usize, end: usize) -> &str { + &self[begin..end] + } + + /// Deprecated: use `s[a..]` instead. + #[unstable(feature = "collections", + reason = "use slice notation [a..b] instead")] + #[deprecated(since = "1.0.0", reason = "use slice notation [a..] instead")] + pub fn slice_from(&self, begin: usize) -> &str { + &self[begin..] + } + + /// Deprecated: use `s[..a]` instead. + #[unstable(feature = "collections", + reason = "use slice notation [a..b] instead")] + #[deprecated(since = "1.0.0", reason = "use slice notation [..a] instead")] + pub fn slice_to(&self, end: usize) -> &str { + &self[..end] + } + + /// Returns a slice of the string from the character range [`begin`..`end`). + /// + /// That is, start at the `begin`-th code point of the string and continue + /// to the `end`-th code point. This does not detect or handle edge cases + /// such as leaving a combining character as the first code point of the + /// string. + /// + /// Due to the design of UTF-8, this operation is `O(end)`. See `slice`, + /// `slice_to` and `slice_from` for `O(1)` variants that use byte indices + /// rather than code point indices. + /// + /// # Panics + /// + /// Panics if `begin` > `end` or the either `begin` or `end` are beyond the + /// last character of the string. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.slice_chars(0, 4), "Löwe"); + /// assert_eq!(s.slice_chars(5, 7), "老虎"); + /// ``` + #[unstable(feature = "collections", + reason = "may have yet to prove its worth")] + pub fn slice_chars(&self, begin: usize, end: usize) -> &str { + core_str::StrExt::slice_chars(&self[..], begin, end) + } + + /// Takes a bytewise slice from a string. + /// + /// Returns the substring from [`begin`..`end`). + /// + /// # Unsafety + /// + /// Caller must check both UTF-8 character boundaries and the boundaries of the entire slice as + /// well. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// unsafe { + /// assert_eq!(s.slice_unchecked(0, 21), "Löwe 老虎 Léopard"); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { + core_str::StrExt::slice_unchecked(&self[..], begin, end) + } + + /// Returns `true` if the given `&str` is a prefix of the string. + /// + /// # Examples + /// + /// ``` + /// assert!("banana".starts_with("ba")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + core_str::StrExt::starts_with(&self[..], pat) + } + + /// Returns true if the given `&str` is a suffix of the string. + /// + /// # Examples + /// + /// ```rust + /// assert!("banana".ends_with("nana")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::ends_with(&self[..], pat) + } + + /// Returns a string with all pre- and suffixes that match a pattern repeatedly removed. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: DoubleEndedSearcher<'a> + { + core_str::StrExt::trim_matches(&self[..], pat) + } + + /// Returns a string with all prefixes that match a pattern repeatedly removed. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { + core_str::StrExt::trim_left_matches(&self[..], pat) + } + + /// Returns a string with all suffixes that match a pattern repeatedly removed. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::trim_right_matches(&self[..], pat) + } + + /// Check that `index`-th byte lies at the start and/or end of a UTF-8 code point sequence. + /// + /// The start and end of the string (when `index == self.len()`) are considered to be + /// boundaries. + /// + /// # Panics + /// + /// Panics if `index` is greater than `self.len()`. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// assert!(s.is_char_boundary(0)); + /// // start of `老` + /// assert!(s.is_char_boundary(6)); + /// assert!(s.is_char_boundary(s.len())); + /// + /// // second byte of `ö` + /// assert!(!s.is_char_boundary(2)); + /// + /// // third byte of `老` + /// assert!(!s.is_char_boundary(8)); + /// ``` + #[unstable(feature = "collections", + reason = "naming is uncertain with container conventions")] + pub fn is_char_boundary(&self, index: usize) -> bool { + core_str::StrExt::is_char_boundary(&self[..], index) + } + + /// Given a byte position, return the next char and its index. + /// + /// This can be used to iterate over the Unicode characters of a string. + /// + /// # Panics + /// + /// If `i` is greater than or equal to the length of the string. + /// If `i` is not the index of the beginning of a valid UTF-8 character. + /// + /// # Examples + /// + /// This example manually iterates through the characters of a string; this should normally be + /// done by `.chars()` or `.char_indices()`. + /// + /// ``` + /// use std::str::CharRange; + /// + /// let s = "中华Việt Nam"; + /// let mut i = 0; + /// while i < s.len() { + /// let CharRange {ch, next} = s.char_range_at(i); + /// println!("{}: {}", i, ch); + /// i = next; + /// } + /// ``` + /// + /// This outputs: + /// + /// ```text + /// 0: 中 + /// 3: 华 + /// 6: V + /// 7: i + /// 8: ệ + /// 11: t + /// 12: + /// 13: N + /// 14: a + /// 15: m + /// ``` + #[unstable(feature = "collections", + reason = "naming is uncertain with container conventions")] + pub fn char_range_at(&self, start: usize) -> CharRange { + core_str::StrExt::char_range_at(&self[..], start) + } + + /// Given a byte position, return the previous `char` and its position. + /// + /// This function can be used to iterate over a Unicode string in reverse. + /// + /// Returns 0 for next index if called on start index 0. + /// + /// # Panics + /// + /// If `i` is greater than the length of the string. + /// If `i` is not an index following a valid UTF-8 character. + /// + /// # Examples + /// + /// This example manually iterates through the characters of a string; this should normally be + /// done by `.chars().rev()` or `.char_indices()`. + /// + /// ``` + /// use std::str::CharRange; + /// + /// let s = "中华Việt Nam"; + /// let mut i = s.len(); + /// while i > 0 { + /// let CharRange {ch, next} = s.char_range_at_reverse(i); + /// println!("{}: {}", i, ch); + /// i = next; + /// } + /// ``` + /// + /// This outputs: + /// + /// ```text + /// 16: m + /// 15: a + /// 14: N + /// 13: + /// 12: t + /// 11: ệ + /// 8: i + /// 7: V + /// 6: 华 + /// 3: 中 + /// ``` + #[unstable(feature = "collections", + reason = "naming is uncertain with container conventions")] + pub fn char_range_at_reverse(&self, start: usize) -> CharRange { + core_str::StrExt::char_range_at_reverse(&self[..], start) + } + + /// Given a byte position, return the `char` at that position. + /// + /// # Panics + /// + /// If `i` is greater than or equal to the length of the string. + /// If `i` is not the index of the beginning of a valid UTF-8 character. + /// + /// # Examples + /// + /// ``` + /// let s = "abπc"; + /// assert_eq!(s.char_at(1), 'b'); + /// assert_eq!(s.char_at(2), 'π'); + /// ``` + #[unstable(feature = "collections", + reason = "naming is uncertain with container conventions")] + pub fn char_at(&self, i: usize) -> char { + core_str::StrExt::char_at(&self[..], i) + } + + /// Given a byte position, return the `char` at that position, counting from the end. + /// + /// # Panics + /// + /// If `i` is greater than the length of the string. + /// If `i` is not an index following a valid UTF-8 character. + /// + /// # Examples + /// + /// ``` + /// let s = "abπc"; + /// assert_eq!(s.char_at_reverse(1), 'a'); + /// assert_eq!(s.char_at_reverse(2), 'b'); + /// ``` + #[unstable(feature = "collections", + reason = "naming is uncertain with container conventions")] + pub fn char_at_reverse(&self, i: usize) -> char { + core_str::StrExt::char_at_reverse(&self[..], i) + } + + /// Convert `self` to a byte slice. + /// + /// # Examples + /// + /// ``` + /// assert_eq!("bors".as_bytes(), b"bors"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_bytes(&self) -> &[u8] { + core_str::StrExt::as_bytes(&self[..]) + } + + /// Returns the byte index of the first character of `self` that matches the pattern, if it + /// exists. + /// + /// Returns `None` if it doesn't exist. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find('L'), Some(0)); + /// assert_eq!(s.find('é'), Some(14)); + /// + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find(|c: char| c.is_whitespace()), Some(5)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.find(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option { + core_str::StrExt::find(&self[..], pat) + } + + /// Returns the byte index of the last character of `self` that matches the pattern, if it + /// exists. + /// + /// Returns `None` if it doesn't exist. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.rfind('L'), Some(13)); + /// assert_eq!(s.rfind('é'), Some(14)); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.rfind(|c: char| c.is_whitespace()), Some(12)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.rfind(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rfind(&self[..], pat) + } + + /// Returns the byte index of the first matching substring if it exists. + /// + /// Returns `None` if it doesn't exist. + /// + /// The pattern can be a simple `&str`, or a closure that determines the split. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find_str("老虎 L"), Some(6)); + /// assert_eq!(s.find_str("muffin man"), None); + /// ``` + #[unstable(feature = "collections")] + #[deprecated(since = "1.0.0", reason = "use `find()` with a `&str`")] + pub fn find_str<'a, P: Pattern<'a>>(&'a self, needle: P) -> Option { + core_str::StrExt::find_str(&self[..], needle) + } + + /// Retrieves the first character from a `&str` and returns it. + /// + /// This does not allocate a new string; instead, it returns a slice that points one character + /// beyond the character that was shifted. + /// + /// If the slice does not contain any characters, None is returned instead. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let (c, s1) = s.slice_shift_char().unwrap(); + /// + /// assert_eq!(c, 'L'); + /// assert_eq!(s1, "öwe 老虎 Léopard"); + /// + /// let (c, s2) = s1.slice_shift_char().unwrap(); + /// + /// assert_eq!(c, 'ö'); + /// assert_eq!(s2, "we 老虎 Léopard"); + /// ``` + #[unstable(feature = "collections", + reason = "awaiting conventions about shifting and slices")] + pub fn slice_shift_char(&self) -> Option<(char, &str)> { + core_str::StrExt::slice_shift_char(&self[..]) + } + + /// Returns the byte offset of an inner slice relative to an enclosing outer slice. + /// + /// # Panics + /// + /// Panics if `inner` is not a direct slice contained within self. + /// + /// # Examples + /// + /// ``` + /// let string = "a\nb\nc"; + /// let lines: Vec<&str> = string.lines().collect(); + /// + /// assert!(string.subslice_offset(lines[0]) == 0); // &"a" + /// assert!(string.subslice_offset(lines[1]) == 2); // &"b" + /// assert!(string.subslice_offset(lines[2]) == 4); // &"c" + /// ``` + #[unstable(feature = "collections", + reason = "awaiting convention about comparability of arbitrary slices")] + pub fn subslice_offset(&self, inner: &str) -> usize { + core_str::StrExt::subslice_offset(&self[..], inner) + } + + /// Return an unsafe pointer to the `&str`'s buffer. + /// + /// The caller must ensure that the string outlives this pointer, and that it is not + /// reallocated (e.g. by pushing to the string). + /// + /// # Examples + /// + /// ``` + /// let s = "Hello"; + /// let p = s.as_ptr(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn as_ptr(&self) -> *const u8 { + core_str::StrExt::as_ptr(&self[..]) + } + + /// Return an iterator of `u16` over the string encoded as UTF-16. + #[unstable(feature = "collections", + reason = "this functionality may only be provided by libunicode")] + pub fn utf16_units(&self) -> Utf16Units { + Utf16Units { encoder: Utf16Encoder::new(self[..].chars()) } + } + + /// Returns the length of `self` in bytes. + /// + /// # Examples + /// + /// ``` + /// assert_eq!("foo".len(), 3); + /// assert_eq!("ƒoo".len(), 4); // fancy f! + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn len(&self) -> usize { + core_str::StrExt::len(&self[..]) + } + + /// Returns true if this slice has a length of zero bytes. + /// + /// # Examples + /// + /// ``` + /// assert!("".is_empty()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + core_str::StrExt::is_empty(&self[..]) + } + + /// Parses `self` into the specified type. + /// + /// # Failure + /// + /// Will return `Err` if it's not possible to parse `self` into the type. + /// + /// # Example + /// + /// ``` + /// assert_eq!("4".parse::(), Ok(4)); + /// ``` + /// + /// Failing: + /// + /// ``` + /// assert!("j".parse::().is_err()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn parse(&self) -> Result { + core_str::StrExt::parse(&self[..]) + } + + /// Returns an iterator over the [grapheme clusters][graphemes] of `self`. + /// + /// [graphemes]: http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries + /// + /// If `is_extended` is true, the iterator is over the *extended grapheme clusters*; + /// otherwise, the iterator is over the *legacy grapheme clusters*. + /// [UAX#29](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) + /// recommends extended grapheme cluster boundaries for general processing. + /// + /// # Examples + /// + /// ``` + /// let gr1 = "a\u{310}e\u{301}o\u{308}\u{332}".graphemes(true).collect::>(); + /// let b: &[_] = &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"]; + /// + /// assert_eq!(gr1.as_slice(), b); + /// + /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::>(); + /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"]; + /// + /// assert_eq!(gr2.as_slice(), b); + /// ``` + #[unstable(feature = "collections", + reason = "this functionality may only be provided by libunicode")] + pub fn graphemes(&self, is_extended: bool) -> Graphemes { + UnicodeStr::graphemes(&self[..], is_extended) + } + + /// Returns an iterator over the grapheme clusters of `self` and their byte offsets. See + /// `graphemes()` for more information. + /// + /// # Examples + /// + /// ``` + /// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::>(); + /// let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; + /// + /// assert_eq!(gr_inds.as_slice(), b); + /// ``` + #[unstable(feature = "collections", + reason = "this functionality may only be provided by libunicode")] + pub fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices { + UnicodeStr::grapheme_indices(&self[..], is_extended) + } + + /// An iterator over the non-empty words of `self`. + /// + /// A 'word' is a subsequence separated by any sequence of whitespace. Sequences of whitespace + /// are collapsed, so empty "words" are not included. + /// + /// # Examples + /// + /// ``` + /// let some_words = " Mary had\ta little \n\t lamb"; + /// let v: Vec<&str> = some_words.words().collect(); + /// + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); + /// ``` + #[unstable(feature = "str_words", + reason = "the precise algorithm to use is unclear")] + pub fn words(&self) -> Words { + UnicodeStr::words(&self[..]) + } + + /// Returns a string's displayed width in columns. + /// + /// Control characters have zero width. + /// + /// `is_cjk` determines behavior for characters in the Ambiguous category: if `is_cjk` is + /// `true`, these are 2 columns wide; otherwise, they are 1. In CJK locales, `is_cjk` should be + /// `true`, else it should be `false`. + /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) recommends that these + /// characters be treated as 1 column (i.e., `is_cjk = false`) if the locale is unknown. + #[unstable(feature = "collections", + reason = "this functionality may only be provided by libunicode")] + pub fn width(&self, is_cjk: bool) -> usize { + UnicodeStr::width(&self[..], is_cjk) + } + + /// Returns a `&str` with leading and trailing whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim(), "Hello\tworld"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim(&self) -> &str { + UnicodeStr::trim(&self[..]) + } + + /// Returns a `&str` with leading whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim_left(), "Hello\tworld\t"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_left(&self) -> &str { + UnicodeStr::trim_left(&self[..]) + } + + /// Returns a `&str` with trailing whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim_right(), " Hello\tworld"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_right(&self) -> &str { + UnicodeStr::trim_right(&self[..]) + } + + /// Returns the lowercase equivalent of this string. + /// + /// # Examples + /// + /// let s = "HELLO"; + /// assert_eq!(s.to_lowercase(), "hello"); + #[unstable(feature = "collections")] + pub fn to_lowercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + s.extend(self[..].chars().flat_map(|c| c.to_lowercase())); + return s; + } + + /// Returns the uppercase equivalent of this string. + /// + /// # Examples + /// + /// let s = "hello"; + /// assert_eq!(s.to_uppercase(), "HELLO"); + #[unstable(feature = "collections")] + pub fn to_uppercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + s.extend(self[..].chars().flat_map(|c| c.to_uppercase())); + return s; + } +} + #[cfg(test)] mod tests { use prelude::*; diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 677894ba6e4c4..47069a81d8585 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -23,6 +23,7 @@ use ops::Deref; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; use slice::{self, SliceExt}; +#[cfg(stage0)] use str::StrExt; use string::String; use vec::Vec; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 35ef375174ad0..ce3b690098fc6 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -25,7 +25,10 @@ use result::Result::{Ok, Err}; use result; use slice::{self, SliceExt}; use string::String; +#[cfg(stage0)] use str::{self, StrExt}; +#[cfg(not(stage0))] +use str; use vec::Vec; pub use self::buffered::{BufReader, BufWriter, BufStream, LineWriter}; diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index fa24e9fd5afc5..968ffcf62257c 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -24,6 +24,7 @@ use num::{self, Int, Float, ToPrimitive}; use num::FpCategory as Fp; use ops::FnMut; use slice::SliceExt; +#[cfg(stage0)] use str::StrExt; use string::String; use vec::Vec; diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index 711faa98bd92e..23a7c3d1114ac 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -269,6 +269,7 @@ use result::Result; use result::Result::{Ok, Err}; use sys; use slice::SliceExt; +#[cfg(stage0)] use str::StrExt; use str; use string::String; diff --git a/src/libstd/old_io/net/ip.rs b/src/libstd/old_io/net/ip.rs index 6e2f491262dea..f71fa9f92baf7 100644 --- a/src/libstd/old_io/net/ip.rs +++ b/src/libstd/old_io/net/ip.rs @@ -27,7 +27,10 @@ use option::Option; use option::Option::{None, Some}; use result::Result::{self, Ok, Err}; use slice::SliceExt; +#[cfg(stage0)] use str::{FromStr, StrExt}; +#[cfg(not(stage0))] +use str::FromStr; use vec::Vec; pub type Port = u16; diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index cabba8e358af0..647ef7306178a 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -761,7 +761,7 @@ mod tests { use old_io::{Truncate, Write, TimedOut, timer, process, FileNotFound}; use prelude::v1::{Ok, Err, range, drop, Some, None, Vec}; use prelude::v1::{Path, String, Reader, Writer, Clone}; - use prelude::v1::{SliceExt, Str, StrExt, AsSlice, ToString, GenericPath}; + use prelude::v1::{SliceExt, Str, AsSlice, ToString, GenericPath}; use old_io::fs::PathExtensions; use old_io::timer::*; use rt::running_on_valgrind; diff --git a/src/libstd/old_io/stdio.rs b/src/libstd/old_io/stdio.rs index dcc3450573093..0e6a4b60e773b 100644 --- a/src/libstd/old_io/stdio.rs +++ b/src/libstd/old_io/stdio.rs @@ -44,6 +44,7 @@ use ptr; use result::Result::{Ok, Err}; use rt; use slice::SliceExt; +#[cfg(stage0)] use str::StrExt; use string::String; use sys::{fs, tty}; diff --git a/src/libstd/old_io/tempfile.rs b/src/libstd/old_io/tempfile.rs index 76753dca52e1e..b34804fce61c0 100644 --- a/src/libstd/old_io/tempfile.rs +++ b/src/libstd/old_io/tempfile.rs @@ -21,6 +21,7 @@ use option::Option; use old_path::{Path, GenericPath}; use rand::{Rng, thread_rng}; use result::Result::{Ok, Err}; +#[cfg(stage0)] use str::StrExt; use string::String; diff --git a/src/libstd/old_path/mod.rs b/src/libstd/old_path/mod.rs index 01eec230d210d..3f9cfbd2a07af 100644 --- a/src/libstd/old_path/mod.rs +++ b/src/libstd/old_path/mod.rs @@ -72,6 +72,7 @@ use iter::IteratorExt; use option::Option; use option::Option::{None, Some}; use str; +#[cfg(stage0)] use str::StrExt; use string::{String, CowString}; use slice::SliceExt; diff --git a/src/libstd/old_path/posix.rs b/src/libstd/old_path/posix.rs index 8d5765e1ffe5e..790dd87ae91f8 100644 --- a/src/libstd/old_path/posix.rs +++ b/src/libstd/old_path/posix.rs @@ -21,7 +21,10 @@ use marker::Sized; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; use slice::{AsSlice, Split, SliceExt, SliceConcatExt}; +#[cfg(stage0)] use str::{self, FromStr, StrExt}; +#[cfg(not(stage0))] +use str::{self, FromStr}; use vec::Vec; use super::{BytesContainer, GenericPath, GenericPathUnsafe}; @@ -448,7 +451,7 @@ mod tests { use option::Option::{self, Some, None}; use old_path::GenericPath; use slice::{AsSlice, SliceExt}; - use str::{self, Str, StrExt}; + use str::{self, Str}; use string::ToString; use vec::Vec; diff --git a/src/libstd/old_path/windows.rs b/src/libstd/old_path/windows.rs index 1387d531001be..4e36befefe809 100644 --- a/src/libstd/old_path/windows.rs +++ b/src/libstd/old_path/windows.rs @@ -28,7 +28,10 @@ use mem; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; use slice::{SliceExt, SliceConcatExt}; +#[cfg(stage0)] use str::{SplitTerminator, FromStr, StrExt}; +#[cfg(not(stage0))] +use str::{SplitTerminator, FromStr}; use string::{String, ToString}; use vec::Vec; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 2dea77a3ccdce..2e86931294615 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -57,7 +57,10 @@ use ptr; use result::Result::{Err, Ok}; use result::Result; use slice::{AsSlice, SliceExt}; +#[cfg(stage0)] use str::{Str, StrExt}; +#[cfg(not(stage0))] +use str::Str; use str; use string::{String, ToString}; use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering}; diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index b244f78585231..81cdced58bd80 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -46,8 +46,12 @@ #[doc(no_inline)] pub use result::Result::{self, Ok, Err}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt, AsSlice}; +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use str::{Str, StrExt}; +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] pub use str::Str; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use string::{String, ToString}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 08aa92d5f20dc..db613db74cf4a 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -533,7 +533,7 @@ mod tests { use io::prelude::*; use prelude::v1::{Ok, Err, drop, Some, Vec}; use prelude::v1::{String, Clone}; - use prelude::v1::{SliceExt, Str, StrExt, AsSlice, ToString, GenericPath}; + use prelude::v1::{SliceExt, Str, AsSlice, ToString, GenericPath}; use old_path; use old_io::fs::PathExtensions; use rt::running_on_valgrind; diff --git a/src/test/compile-fail/method-suggestion-no-duplication.rs b/src/test/compile-fail/method-suggestion-no-duplication.rs index e807d2b9448d3..d05e2ba0e1949 100644 --- a/src/test/compile-fail/method-suggestion-no-duplication.rs +++ b/src/test/compile-fail/method-suggestion-no-duplication.rs @@ -20,5 +20,4 @@ fn main() { //~^^ HELP #1: `core::slice::SliceExt` //~^^^ HELP #2: `core::str::StrExt` //~^^^^ HELP #3: `collections::slice::SliceExt` - //~^^^^^ HELP #4: `collections::str::StrExt` } From 633c593bc3f9787decfaf943cdc5659f132ade50 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 10 Mar 2015 23:13:29 -0500 Subject: [PATCH 04/15] impl [T] --- src/libcollections/macros.rs | 38 ++ src/libcollections/slice.rs | 832 +++++++++++++++++++++++++++++ src/libcollections/str.rs | 1 + src/libcollections/string.rs | 17 + src/libcollections/vec.rs | 4 + src/libstd/ffi/c_str.rs | 3 + src/libstd/io/mod.rs | 3 + src/libstd/num/strconv.rs | 1 + src/libstd/old_io/buffered.rs | 1 + src/libstd/old_io/comm_adapters.rs | 3 + src/libstd/old_io/extensions.rs | 2 + src/libstd/old_io/fs.rs | 1 + src/libstd/old_io/mem.rs | 3 + src/libstd/old_io/mod.rs | 1 + src/libstd/old_io/net/ip.rs | 1 + src/libstd/old_io/stdio.rs | 1 + src/libstd/old_path/mod.rs | 1 + src/libstd/old_path/posix.rs | 3 + src/libstd/old_path/windows.rs | 3 + src/libstd/os.rs | 3 + src/libstd/prelude/v1.rs | 4 + src/libstd/rand/os.rs | 3 + src/libstd/rand/reader.rs | 1 + src/libstd/sys/common/wtf8.rs | 12 + src/libstd/sys/unix/os_str.rs | 1 + 25 files changed, 943 insertions(+) diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index 0f6a85d75daa8..cb84e01e4f79a 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[cfg(stage0)] /// Creates a `Vec` containing the arguments. /// /// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. @@ -45,6 +46,43 @@ macro_rules! vec { ($($x:expr,)*) => (vec![$($x),*]) } +#[cfg(not(stage0))] +/// Creates a `Vec` containing the arguments. +/// +/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. +/// There are two forms of this macro: +/// +/// - Create a `Vec` containing a given list of elements: +/// +/// ``` +/// let v = vec![1, 2, 3]; +/// assert_eq!(v[0], 1); +/// assert_eq!(v[1], 2); +/// assert_eq!(v[2], 3); +/// ``` +/// +/// - Create a `Vec` from a given element and size: +/// +/// ``` +/// let v = vec![1; 3]; +/// assert_eq!(v, [1, 1, 1]); +/// ``` +/// +/// Note that unlike array expressions this syntax supports all elements +/// which implement `Clone` and the number of elements doesn't have to be +/// a constant. +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +macro_rules! vec { + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),*) => ( + <[_]>::into_vec($crate::boxed::Box::new([$($x),*])) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + /// Use the syntax described in `std::fmt` to create a value of type `String`. /// See `std::fmt` for more information. /// diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index e1c27095b2f43..c98d0cb35e1d5 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -120,6 +120,7 @@ pub use core::slice::{from_raw_buf, from_raw_mut_buf}; // Basic slice extension methods //////////////////////////////////////////////////////////////////////////////// +#[cfg(stage0)] /// Allocating extension methods for slices. #[stable(feature = "rust1", since = "1.0.0")] pub trait SliceExt { @@ -795,6 +796,7 @@ pub trait SliceExt { fn into_vec(self: Box) -> Vec; } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl SliceExt for [T] { type Item = T; @@ -1080,6 +1082,836 @@ impl SliceExt for [T] { } } +#[cfg(not(stage0))] +/// Allocating extension methods for slices. +#[lang = "slice"] +#[stable(feature = "rust1", since = "1.0.0")] +impl [T] { + /// Sorts the slice, in place, using `compare` to compare + /// elements. + /// + /// This sort is `O(n log n)` worst-case and stable, but allocates + /// approximately `2 * n`, where `n` is the length of `self`. + /// + /// # Examples + /// + /// ```rust + /// let mut v = [5, 4, 1, 3, 2]; + /// v.sort_by(|a, b| a.cmp(b)); + /// assert!(v == [1, 2, 3, 4, 5]); + /// + /// // reverse sorting + /// v.sort_by(|a, b| b.cmp(a)); + /// assert!(v == [5, 4, 3, 2, 1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sort_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering { + merge_sort(self, compare) + } + + /// Consumes `src` and moves as many elements as it can into `self` + /// from the range [start,end). + /// + /// Returns the number of elements copied (the shorter of `self.len()` + /// and `end - start`). + /// + /// # Arguments + /// + /// * src - A mutable vector of `T` + /// * start - The index into `src` to start copying from + /// * end - The index into `src` to stop copying from + /// + /// # Examples + /// + /// ```rust + /// let mut a = [1, 2, 3, 4, 5]; + /// let b = vec![6, 7, 8]; + /// let num_moved = a.move_from(b, 0, 3); + /// assert_eq!(num_moved, 3); + /// assert!(a == [6, 7, 8, 4, 5]); + /// ``` + #[unstable(feature = "collections", + reason = "uncertain about this API approach")] + #[inline] + pub fn move_from(&mut self, mut src: Vec, start: usize, end: usize) -> usize { + for (a, b) in self.iter_mut().zip(src[start .. end].iter_mut()) { + mem::swap(a, b); + } + cmp::min(self.len(), end-start) + } + + /// Deprecated: use `&s[start .. end]` notation instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &s[start .. end] instead")] + #[inline] + pub fn slice(&self, start: usize, end: usize) -> &[T] { + &self[start .. end] + } + + /// Deprecated: use `&s[start..]` notation instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &s[start..] instead")] + #[inline] + pub fn slice_from(&self, start: usize) -> &[T] { + &self[start ..] + } + + /// Deprecated: use `&s[..end]` notation instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &s[..end] instead")] + #[inline] + pub fn slice_to(&self, end: usize) -> &[T] { + &self[.. end] + } + + /// Divides one slice into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// Panics if `mid > len`. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30, 20, 50]; + /// let (v1, v2) = v.split_at(2); + /// assert_eq!([10, 40], v1); + /// assert_eq!([30, 20, 50], v2); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_at(&self, mid: usize) -> (&[T], &[T]) { + core_slice::SliceExt::split_at(self, mid) + } + + /// Returns an iterator over the slice. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn iter(&self) -> Iter { + core_slice::SliceExt::iter(self) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`. The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// Print the slice split by numbers divisible by 3 (i.e. `[10, 40]`, + /// `[20]`, `[50]`): + /// + /// ``` + /// let v = [10, 40, 30, 20, 60, 50]; + /// for group in v.split(|num| *num % 3 == 0) { + /// println!("{:?}", group); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split(&self, pred: F) -> Split where F: FnMut(&T) -> bool { + core_slice::SliceExt::split(self, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`, limited to splitting at most `n` times. The matched element is + /// not contained in the subslices. + /// + /// # Examples + /// + /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`, + /// `[20, 60, 50]`): + /// + /// ``` + /// let v = [10, 40, 30, 20, 60, 50]; + /// for group in v.splitn(1, |num| *num % 3 == 0) { + /// println!("{:?}", group); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn(&self, n: usize, pred: F) -> SplitN where F: FnMut(&T) -> bool { + core_slice::SliceExt::splitn(self, n, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred` limited to splitting at most `n` times. This starts at the end of + /// the slice and works backwards. The matched element is not contained in + /// the subslices. + /// + /// # Examples + /// + /// Print the slice split once, starting from the end, by numbers divisible + /// by 3 (i.e. `[50]`, `[10, 40, 30, 20]`): + /// + /// ``` + /// let v = [10, 40, 30, 20, 60, 50]; + /// for group in v.rsplitn(1, |num| *num % 3 == 0) { + /// println!("{:?}", group); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn(&self, n: usize, pred: F) -> RSplitN where F: FnMut(&T) -> bool { + core_slice::SliceExt::rsplitn(self, n, pred) + } + + /// Returns an iterator over all contiguous windows of length + /// `size`. The windows overlap. If the slice is shorter than + /// `size`, the iterator returns no values. + /// + /// # Panics + /// + /// Panics if `size` is 0. + /// + /// # Example + /// + /// Print the adjacent pairs of a slice (i.e. `[1,2]`, `[2,3]`, + /// `[3,4]`): + /// + /// ```rust + /// let v = &[1, 2, 3, 4]; + /// for win in v.windows(2) { + /// println!("{:?}", win); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn windows(&self, size: usize) -> Windows { + core_slice::SliceExt::windows(self, size) + } + + /// Returns an iterator over `size` elements of the slice at a + /// time. The chunks do not overlap. If `size` does not divide the + /// length of the slice, then the last chunk will not have length + /// `size`. + /// + /// # Panics + /// + /// Panics if `size` is 0. + /// + /// # Example + /// + /// Print the slice two elements at a time (i.e. `[1,2]`, + /// `[3,4]`, `[5]`): + /// + /// ```rust + /// let v = &[1, 2, 3, 4, 5]; + /// for win in v.chunks(2) { + /// println!("{:?}", win); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn chunks(&self, size: usize) -> Chunks { + core_slice::SliceExt::chunks(self, size) + } + + /// Returns the element of a slice at the given index, or `None` if the + /// index is out of bounds. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&40), v.get(1)); + /// assert_eq!(None, v.get(3)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn get(&self, index: usize) -> Option<&T> { + core_slice::SliceExt::get(self, index) + } + + /// Returns the first element of a slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&10), v.first()); + /// + /// let w: &[i32] = &[]; + /// assert_eq!(None, w.first()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn first(&self) -> Option<&T> { + core_slice::SliceExt::first(self) + } + + /// Returns all but the first element of a slice. + #[unstable(feature = "collections", reason = "likely to be renamed")] + #[inline] + pub fn tail(&self) -> &[T] { + core_slice::SliceExt::tail(self) + } + + /// Returns all but the last element of a slice. + #[unstable(feature = "collections", reason = "likely to be renamed")] + #[inline] + pub fn init(&self) -> &[T] { + core_slice::SliceExt::init(self) + } + + /// Returns the last element of a slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&30), v.last()); + /// + /// let w: &[i32] = &[]; + /// assert_eq!(None, w.last()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn last(&self) -> Option<&T> { + core_slice::SliceExt::last(self) + } + + /// Returns a pointer to the element at the given index, without doing + /// bounds checking. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn get_unchecked(&self, index: usize) -> &T { + core_slice::SliceExt::get_unchecked(self, index) + } + + /// Returns an unsafe pointer to the slice's buffer + /// + /// The caller must ensure that the slice outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// + /// Modifying the slice may cause its buffer to be reallocated, which + /// would also make any pointers to it invalid. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn as_ptr(&self) -> *const T { + core_slice::SliceExt::as_ptr(self) + } + + /// Binary search a sorted slice with a comparator function. + /// + /// The comparator function should implement an order consistent + /// with the sort order of the underlying slice, returning an + /// order code that indicates whether its argument is `Less`, + /// `Equal` or `Greater` the desired target. + /// + /// If a matching value is found then returns `Ok`, containing + /// the index for the matched element; if no match is found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// # Example + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1,4]`. + /// + /// ```rust + /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = s.as_slice(); + /// + /// let seek = 13; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9)); + /// let seek = 4; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7)); + /// let seek = 100; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13)); + /// let seek = 1; + /// let r = s.binary_search_by(|probe| probe.cmp(&seek)); + /// assert!(match r { Ok(1...4) => true, _ => false, }); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn binary_search_by(&self, f: F) -> Result where F: FnMut(&T) -> Ordering { + core_slice::SliceExt::binary_search_by(self, f) + } + + /// Return the number of elements in the slice + /// + /// # Example + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert_eq!(a.len(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn len(&self) -> usize { + core_slice::SliceExt::len(self) + } + + /// Returns true if the slice has a length of 0 + /// + /// # Example + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert!(!a.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_empty(&self) -> bool { + core_slice::SliceExt::is_empty(self) + } + + /// Returns a mutable reference to the element at the given index, + /// or `None` if the index is out of bounds + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { + core_slice::SliceExt::get_mut(self, index) + } + + /// Work with `self` as a mut slice. + /// Primarily intended for getting a &mut [T] from a [T; N]. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + core_slice::SliceExt::as_mut_slice(self) + } + + /// Deprecated: use `&mut s[start .. end]` instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[start .. end] instead")] + #[inline] + pub fn slice_mut(&mut self, start: usize, end: usize) -> &mut [T] { + &mut self[start .. end] + } + + /// Deprecated: use `&mut s[start ..]` instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[start ..] instead")] + #[inline] + pub fn slice_from_mut(&mut self, start: usize) -> &mut [T] { + &mut self[start ..] + } + + /// Deprecated: use `&mut s[.. end]` instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[.. end] instead")] + #[inline] + pub fn slice_to_mut(&mut self, end: usize) -> &mut [T] { + &mut self[.. end] + } + + /// Returns an iterator that allows modifying each value + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn iter_mut(&mut self) -> IterMut { + core_slice::SliceExt::iter_mut(self) + } + + /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn first_mut(&mut self) -> Option<&mut T> { + core_slice::SliceExt::first_mut(self) + } + + /// Returns all but the first element of a mutable slice + #[unstable(feature = "collections", + reason = "likely to be renamed or removed")] + #[inline] + pub fn tail_mut(&mut self) -> &mut [T] { + core_slice::SliceExt::tail_mut(self) + } + + /// Returns all but the last element of a mutable slice + #[unstable(feature = "collections", + reason = "likely to be renamed or removed")] + #[inline] + pub fn init_mut(&mut self) -> &mut [T] { + core_slice::SliceExt::init_mut(self) + } + + /// Returns a mutable pointer to the last item in the slice. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn last_mut(&mut self) -> Option<&mut T> { + core_slice::SliceExt::last_mut(self) + } + + /// Returns an iterator over mutable subslices separated by elements that + /// match `pred`. The matched element is not contained in the subslices. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_mut(&mut self, pred: F) -> SplitMut where F: FnMut(&T) -> bool { + core_slice::SliceExt::split_mut(self, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`, limited to splitting at most `n` times. The matched element is + /// not contained in the subslices. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn_mut(&mut self, n: usize, pred: F) -> SplitNMut + where F: FnMut(&T) -> bool { + core_slice::SliceExt::splitn_mut(self, n, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred` limited to splitting at most `n` times. This starts at the end of + /// the slice and works backwards. The matched element is not contained in + /// the subslices. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn_mut(&mut self, n: usize, pred: F) -> RSplitNMut + where F: FnMut(&T) -> bool { + core_slice::SliceExt::rsplitn_mut(self, n, pred) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time. + /// The chunks are mutable and do not overlap. If `chunk_size` does + /// not divide the length of the slice, then the last chunk will not + /// have length `chunk_size`. + /// + /// # Panics + /// + /// Panics if `chunk_size` is 0. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut { + core_slice::SliceExt::chunks_mut(self, chunk_size) + } + + /// Swaps two elements in a slice. + /// + /// # Arguments + /// + /// * a - The index of the first element + /// * b - The index of the second element + /// + /// # Panics + /// + /// Panics if `a` or `b` are out of bounds. + /// + /// # Example + /// + /// ```rust + /// let mut v = ["a", "b", "c", "d"]; + /// v.swap(1, 3); + /// assert!(v == ["a", "d", "c", "b"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn swap(&mut self, a: usize, b: usize) { + core_slice::SliceExt::swap(self, a, b) + } + + /// Divides one `&mut` into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `mid > len`. + /// + /// # Example + /// + /// ```rust + /// let mut v = [1, 2, 3, 4, 5, 6]; + /// + /// // scoped to restrict the lifetime of the borrows + /// { + /// let (left, right) = v.split_at_mut(0); + /// assert!(left == []); + /// assert!(right == [1, 2, 3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at_mut(2); + /// assert!(left == [1, 2]); + /// assert!(right == [3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at_mut(6); + /// assert!(left == [1, 2, 3, 4, 5, 6]); + /// assert!(right == []); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + core_slice::SliceExt::split_at_mut(self, mid) + } + + /// Reverse the order of elements in a slice, in place. + /// + /// # Example + /// + /// ```rust + /// let mut v = [1, 2, 3]; + /// v.reverse(); + /// assert!(v == [3, 2, 1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn reverse(&mut self) { + core_slice::SliceExt::reverse(self) + } + + /// Returns an unsafe mutable pointer to the element in index + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T { + core_slice::SliceExt::get_unchecked_mut(self, index) + } + + /// Return an unsafe mutable pointer to the slice's buffer. + /// + /// The caller must ensure that the slice outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// + /// Modifying the slice may cause its buffer to be reallocated, which + /// would also make any pointers to it invalid. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + core_slice::SliceExt::as_mut_ptr(self) + } + + /// Copies `self` into a new `Vec`. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_vec(&self) -> Vec where T: Clone { + let mut vector = Vec::with_capacity(self.len()); + vector.push_all(self); + vector + } + + /// Creates an iterator that yields every possible permutation of the + /// vector in succession. + /// + /// # Examples + /// + /// ```rust + /// let v = [1, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// for p in perms { + /// println!("{:?}", p); + /// } + /// ``` + /// + /// Iterating through permutations one by one. + /// + /// ```rust + /// let v = [1, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// assert_eq!(Some(vec![1, 2, 3]), perms.next()); + /// assert_eq!(Some(vec![1, 3, 2]), perms.next()); + /// assert_eq!(Some(vec![3, 1, 2]), perms.next()); + /// ``` + #[unstable(feature = "collections")] + pub fn permutations(&self) -> Permutations where T: Clone { + Permutations{ + swaps: ElementSwaps::new(self.len()), + v: self.to_vec(), + } + } + + /// Copies as many elements from `src` as it can into `self` (the + /// shorter of `self.len()` and `src.len()`). Returns the number + /// of elements copied. + /// + /// # Example + /// + /// ```rust + /// let mut dst = [0, 0, 0]; + /// let src = [1, 2]; + /// + /// assert!(dst.clone_from_slice(&src) == 2); + /// assert!(dst == [1, 2, 0]); + /// + /// let src2 = [3, 4, 5, 6]; + /// assert!(dst.clone_from_slice(&src2) == 3); + /// assert!(dst == [3, 4, 5]); + /// ``` + #[unstable(feature = "collections")] + pub fn clone_from_slice(&mut self, src: &[T]) -> usize where T: Clone { + core_slice::SliceExt::clone_from_slice(self, src) + } + + /// Sorts the slice, in place. + /// + /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. + /// + /// # Examples + /// + /// ```rust + /// let mut v = [-5, 4, 1, -3, 2]; + /// + /// v.sort(); + /// assert!(v == [-5, -3, 1, 2, 4]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sort(&mut self) where T: Ord { + self.sort_by(|a, b| a.cmp(b)) + } + + /// Binary search a sorted slice for a given element. + /// + /// If the value is found then `Ok` is returned, containing the + /// index of the matching element; if the value is not found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// # Example + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1,4]`. + /// + /// ```rust + /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = s.as_slice(); + /// + /// assert_eq!(s.binary_search(&13), Ok(9)); + /// assert_eq!(s.binary_search(&4), Err(7)); + /// assert_eq!(s.binary_search(&100), Err(13)); + /// let r = s.binary_search(&1); + /// assert!(match r { Ok(1...4) => true, _ => false, }); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn binary_search(&self, x: &T) -> Result where T: Ord { + core_slice::SliceExt::binary_search(self, x) + } + + /// Deprecated: use `binary_search` instead. + #[unstable(feature = "collections")] + #[deprecated(since = "1.0.0", reason = "use binary_search instead")] + pub fn binary_search_elem(&self, x: &T) -> Result where T: Ord { + self.binary_search(x) + } + + /// Mutates the slice to the next lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// last-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [0, 1, 2]; + /// v.next_permutation(); + /// let b: &mut [_] = &mut [0, 2, 1]; + /// assert!(v == b); + /// v.next_permutation(); + /// let b: &mut [_] = &mut [1, 0, 2]; + /// assert!(v == b); + /// ``` + #[unstable(feature = "collections", + reason = "uncertain if this merits inclusion in std")] + pub fn next_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::next_permutation(self) + } + + /// Mutates the slice to the previous lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// first-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [1, 0, 2]; + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0, 2, 1]; + /// assert!(v == b); + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0, 1, 2]; + /// assert!(v == b); + /// ``` + #[unstable(feature = "collections", + reason = "uncertain if this merits inclusion in std")] + pub fn prev_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::prev_permutation(self) + } + + /// Find the first index containing a matching value. + #[unstable(feature = "collections")] + pub fn position_elem(&self, t: &T) -> Option where T: PartialEq { + core_slice::SliceExt::position_elem(self, t) + } + + /// Find the last index containing a matching value. + #[unstable(feature = "collections")] + pub fn rposition_elem(&self, t: &T) -> Option where T: PartialEq { + core_slice::SliceExt::rposition_elem(self, t) + } + + /// Returns true if the slice contains an element with the given value. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.contains(&30)); + /// assert!(!v.contains(&50)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn contains(&self, x: &T) -> bool where T: PartialEq { + core_slice::SliceExt::contains(self, x) + } + + /// Returns true if `needle` is a prefix of the slice. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.starts_with(&[10])); + /// assert!(v.starts_with(&[10, 40])); + /// assert!(!v.starts_with(&[50])); + /// assert!(!v.starts_with(&[10, 50])); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::starts_with(self, needle) + } + + /// Returns true if `needle` is a suffix of the slice. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.ends_with(&[30])); + /// assert!(v.ends_with(&[40, 30])); + /// assert!(!v.ends_with(&[50])); + /// assert!(!v.ends_with(&[50, 30])); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::ends_with(self, needle) + } + + /// Convert `self` into a vector without clones or allocation. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_vec(mut self: Box) -> Vec { + unsafe { + let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); + mem::forget(self); + xs + } + } +} + //////////////////////////////////////////////////////////////////////////////// // Extension traits for slices over specific kinds of data //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index b4e548e137e94..06674f6f0ab75 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -72,6 +72,7 @@ use unicode::str::{UnicodeStr, Utf16Encoder}; use vec_deque::VecDeque; use borrow::{Borrow, ToOwned}; +#[cfg(stage0)] use slice::SliceExt; use string::String; use unicode; diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index e7f76698b4088..64dec9731ec21 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -85,6 +85,7 @@ impl String { } } + #[cfg(stage0)] /// Creates a new string buffer from the given string. /// /// # Examples @@ -100,6 +101,22 @@ impl String { String { vec: ::slice::SliceExt::to_vec(string.as_bytes()) } } + #[cfg(not(stage0))] + /// Creates a new string buffer from the given string. + /// + /// # Examples + /// + /// ``` + /// let s = String::from_str("hello"); + /// assert_eq!(s.as_slice(), "hello"); + /// ``` + #[inline] + #[unstable(feature = "collections", + reason = "needs investigation to see if to_string() can match perf")] + pub fn from_str(string: &str) -> String { + String { vec: <[_]>::to_vec(string.as_bytes()) } + } + /// Returns the vector as a string buffer, if possible, taking care not to /// copy it. /// diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 8a2c58e0b5d27..937df5494dffa 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1282,8 +1282,12 @@ pub fn from_elem(elem: T, n: usize) -> Vec { #[unstable(feature = "collections")] impl Clone for Vec { + #[cfg(stage0)] fn clone(&self) -> Vec { ::slice::SliceExt::to_vec(&**self) } + #[cfg(not(stage0))] + fn clone(&self) -> Vec { <[T]>::to_vec(&**self) } + fn clone_from(&mut self, other: &Vec) { // drop anything in self that will not be overwritten if self.len() > other.len() { diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 47069a81d8585..48526f2bf2db4 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -22,7 +22,10 @@ use old_io; use ops::Deref; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; +#[cfg(stage0)] use slice::{self, SliceExt}; +#[cfg(not(stage0))] +use slice; #[cfg(stage0)] use str::StrExt; use string::String; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index ce3b690098fc6..c89edf7284293 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -23,7 +23,10 @@ use option::Option::{self, Some, None}; use ptr::PtrExt; use result::Result::{Ok, Err}; use result; +#[cfg(stage0)] use slice::{self, SliceExt}; +#[cfg(not(stage0))] +use slice; use string::String; #[cfg(stage0)] use str::{self, StrExt}; diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 968ffcf62257c..ea1e05df85f75 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -23,6 +23,7 @@ use char; use num::{self, Int, Float, ToPrimitive}; use num::FpCategory as Fp; use ops::FnMut; +#[cfg(stage0)] use slice::SliceExt; #[cfg(stage0)] use str::StrExt; diff --git a/src/libstd/old_io/buffered.rs b/src/libstd/old_io/buffered.rs index 3ee73f5ff6033..2f4e1e870997d 100644 --- a/src/libstd/old_io/buffered.rs +++ b/src/libstd/old_io/buffered.rs @@ -20,6 +20,7 @@ use ops::Drop; use option::Option; use option::Option::{Some, None}; use result::Result::Ok; +#[cfg(stage0)] use slice::{SliceExt}; use slice; use vec::Vec; diff --git a/src/libstd/old_io/comm_adapters.rs b/src/libstd/old_io/comm_adapters.rs index 72ba653a9861a..33928d638e064 100644 --- a/src/libstd/old_io/comm_adapters.rs +++ b/src/libstd/old_io/comm_adapters.rs @@ -14,7 +14,10 @@ use sync::mpsc::{Sender, Receiver}; use old_io; use option::Option::{None, Some}; use result::Result::{Ok, Err}; +#[cfg(stage0)] use slice::{bytes, SliceExt}; +#[cfg(not(stage0))] +use slice::bytes; use super::{Buffer, Reader, Writer, IoResult}; use vec::Vec; diff --git a/src/libstd/old_io/extensions.rs b/src/libstd/old_io/extensions.rs index ec30121d78db8..b67ec847c79ae 100644 --- a/src/libstd/old_io/extensions.rs +++ b/src/libstd/old_io/extensions.rs @@ -28,6 +28,7 @@ use option::Option; use option::Option::{Some, None}; use ptr::PtrExt; use result::Result::{Ok, Err}; +#[cfg(stage0)] use slice::SliceExt; /// An iterator that reads a single byte on each iteration, @@ -162,6 +163,7 @@ pub fn u64_to_be_bytes(n: u64, size: uint, f: F) -> T where /// 32-bit value is parsed. pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 { use ptr::{copy_nonoverlapping_memory}; + #[cfg(stage0)] use slice::SliceExt; assert!(size <= 8); diff --git a/src/libstd/old_io/fs.rs b/src/libstd/old_io/fs.rs index b0116bd4efdc4..a6ed76688ca68 100644 --- a/src/libstd/old_io/fs.rs +++ b/src/libstd/old_io/fs.rs @@ -64,6 +64,7 @@ use option::Option::{Some, None}; use old_path::{Path, GenericPath}; use old_path; use result::Result::{Err, Ok}; +#[cfg(stage0)] use slice::SliceExt; use string::String; use vec::Vec; diff --git a/src/libstd/old_io/mem.rs b/src/libstd/old_io/mem.rs index 2445da9ea3bab..a31b2e7627def 100644 --- a/src/libstd/old_io/mem.rs +++ b/src/libstd/old_io/mem.rs @@ -17,7 +17,10 @@ use option::Option::None; use result::Result::{Err, Ok}; use old_io; use old_io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult}; +#[cfg(stage0)] use slice::{self, SliceExt}; +#[cfg(not(stage0))] +use slice; use vec::Vec; const BUF_CAPACITY: uint = 128; diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index 23a7c3d1114ac..89e813de5b628 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -268,6 +268,7 @@ use boxed::Box; use result::Result; use result::Result::{Ok, Err}; use sys; +#[cfg(stage0)] use slice::SliceExt; #[cfg(stage0)] use str::StrExt; diff --git a/src/libstd/old_io/net/ip.rs b/src/libstd/old_io/net/ip.rs index f71fa9f92baf7..2dda2c1277a34 100644 --- a/src/libstd/old_io/net/ip.rs +++ b/src/libstd/old_io/net/ip.rs @@ -26,6 +26,7 @@ use ops::{FnOnce, FnMut}; use option::Option; use option::Option::{None, Some}; use result::Result::{self, Ok, Err}; +#[cfg(stage0)] use slice::SliceExt; #[cfg(stage0)] use str::{FromStr, StrExt}; diff --git a/src/libstd/old_io/stdio.rs b/src/libstd/old_io/stdio.rs index 0e6a4b60e773b..92fad2316714c 100644 --- a/src/libstd/old_io/stdio.rs +++ b/src/libstd/old_io/stdio.rs @@ -43,6 +43,7 @@ use ops::{Deref, DerefMut, FnOnce}; use ptr; use result::Result::{Ok, Err}; use rt; +#[cfg(stage0)] use slice::SliceExt; #[cfg(stage0)] use str::StrExt; diff --git a/src/libstd/old_path/mod.rs b/src/libstd/old_path/mod.rs index 3f9cfbd2a07af..37875658ae091 100644 --- a/src/libstd/old_path/mod.rs +++ b/src/libstd/old_path/mod.rs @@ -75,6 +75,7 @@ use str; #[cfg(stage0)] use str::StrExt; use string::{String, CowString}; +#[cfg(stage0)] use slice::SliceExt; use vec::Vec; diff --git a/src/libstd/old_path/posix.rs b/src/libstd/old_path/posix.rs index 790dd87ae91f8..9ac7512c00b70 100644 --- a/src/libstd/old_path/posix.rs +++ b/src/libstd/old_path/posix.rs @@ -20,7 +20,10 @@ use iter::{Iterator, IteratorExt, Map}; use marker::Sized; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; +#[cfg(stage0)] use slice::{AsSlice, Split, SliceExt, SliceConcatExt}; +#[cfg(not(stage0))] +use slice::{AsSlice, Split, SliceConcatExt}; #[cfg(stage0)] use str::{self, FromStr, StrExt}; #[cfg(not(stage0))] diff --git a/src/libstd/old_path/windows.rs b/src/libstd/old_path/windows.rs index 4e36befefe809..b74bee1242de7 100644 --- a/src/libstd/old_path/windows.rs +++ b/src/libstd/old_path/windows.rs @@ -27,7 +27,10 @@ use iter::{Iterator, IteratorExt, Map, repeat}; use mem; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; +#[cfg(stage0)] use slice::{SliceExt, SliceConcatExt}; +#[cfg(not(stage0))] +use slice::SliceConcatExt; #[cfg(stage0)] use str::{SplitTerminator, FromStr, StrExt}; #[cfg(not(stage0))] diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 2e86931294615..e04d7f3f240cb 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -56,7 +56,10 @@ use ptr::PtrExt; use ptr; use result::Result::{Err, Ok}; use result::Result; +#[cfg(stage0)] use slice::{AsSlice, SliceExt}; +#[cfg(not(stage0))] +use slice::AsSlice; #[cfg(stage0)] use str::{Str, StrExt}; #[cfg(not(stage0))] diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 81cdced58bd80..e21ae1657ee51 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -44,8 +44,12 @@ #[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use result::Result::{self, Ok, Err}; +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt, AsSlice}; +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] pub use slice::{SliceConcatExt, AsSlice}; #[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use str::{Str, StrExt}; diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 6cb3eb4d16e61..46e35e0fa8bf0 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -24,6 +24,7 @@ mod imp { use rand::Rng; use rand::reader::ReaderRng; use result::Result::Ok; + #[cfg(stage0)] use slice::SliceExt; use mem; use os::errno; @@ -193,6 +194,7 @@ mod imp { use rand::Rng; use result::Result::{Ok}; use self::libc::{c_int, size_t}; + #[cfg(stage0)] use slice::SliceExt; /// A random number generator that retrieves randomness straight from @@ -263,6 +265,7 @@ mod imp { use result::Result::{Ok, Err}; use self::libc::{DWORD, BYTE, LPCSTR, BOOL}; use self::libc::types::os::arch::extra::{LONG_PTR}; + #[cfg(stage0)] use slice::SliceExt; type HCRYPTPROV = LONG_PTR; diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs index 08c43198aa1f1..eac5aa4256c8c 100644 --- a/src/libstd/rand/reader.rs +++ b/src/libstd/rand/reader.rs @@ -13,6 +13,7 @@ use old_io::Reader; use rand::Rng; use result::Result::{Ok, Err}; +#[cfg(stage0)] use slice::SliceExt; /// An RNG that reads random bytes straight from a `Reader`. This will diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index 4c0b26f8649d8..dfc88571a8282 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -172,6 +172,7 @@ impl Wtf8Buf { Wtf8Buf { bytes: string.into_bytes() } } + #[cfg(stage0)] /// Create a WTF-8 string from an UTF-8 `&str` slice. /// /// This copies the content of the slice. @@ -182,6 +183,17 @@ impl Wtf8Buf { Wtf8Buf { bytes: slice::SliceExt::to_vec(str.as_bytes()) } } + #[cfg(not(stage0))] + /// Create a WTF-8 string from an UTF-8 `&str` slice. + /// + /// This copies the content of the slice. + /// + /// Since WTF-8 is a superset of UTF-8, this always succeeds. + #[inline] + pub fn from_str(str: &str) -> Wtf8Buf { + Wtf8Buf { bytes: <[_]>::to_vec(str.as_bytes()) } + } + /// Create a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units. /// /// This is lossless: calling `.encode_wide()` on the resulting string diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs index 89ab3e1981be4..995914807528b 100644 --- a/src/libstd/sys/unix/os_str.rs +++ b/src/libstd/sys/unix/os_str.rs @@ -16,6 +16,7 @@ use core::prelude::*; use borrow::Cow; use fmt::{self, Debug}; use vec::Vec; +#[cfg(stage0)] use slice::SliceExt as StdSliceExt; use str; use string::String; From 8afcaabee32fb41eaf065041d7510c6762f12822 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 10 Mar 2015 23:13:36 -0500 Subject: [PATCH 05/15] impl *const T, impl *mut T --- src/liballoc/heap.rs | 1 + src/liballoc/rc.rs | 3 + src/libcollections/slice.rs | 1 + src/libcore/prelude.rs | 1 + src/libcore/ptr.rs | 118 +++++++++++++++++++++++++++ src/libcore/slice.rs | 1 + src/libcore/str/mod.rs | 1 + src/libstd/collections/hash/table.rs | 3 + src/libstd/io/mod.rs | 1 + src/libstd/old_io/extensions.rs | 1 + src/libstd/old_io/mod.rs | 1 + src/libstd/os.rs | 1 + src/libstd/prelude/v1.rs | 1 + src/libstd/rt/at_exit_imp.rs | 1 + 14 files changed, 135 insertions(+) diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index f9936b7a16a9d..d1c8ab348d40a 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[cfg(stage0)] #[cfg(not(test))] use core::ptr::PtrExt; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 115acd4a0efec..3692149db44bc 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -159,7 +159,10 @@ use core::nonzero::NonZero; use core::ops::{Deref, Drop}; use core::option::Option; use core::option::Option::{Some, None}; +#[cfg(stage0)] use core::ptr::{self, PtrExt}; +#[cfg(not(stage0))] +use core::ptr; use core::result::Result; use core::result::Result::{Ok, Err}; use core::intrinsics::assume; diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index c98d0cb35e1d5..0fe513d3118c5 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -99,6 +99,7 @@ use core::mem; use core::num::wrapping::WrappingOps; use core::ops::FnMut; use core::option::Option::{self, Some, None}; +#[cfg(stage0)] use core::ptr::PtrExt; use core::ptr; use core::result::Result; diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 6c79233da68f1..fb793a623904b 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -42,6 +42,7 @@ pub use iter::{Extend, IteratorExt}; pub use iter::{Iterator, DoubleEndedIterator}; pub use iter::{ExactSizeIterator}; pub use option::Option::{self, Some, None}; +#[cfg(stage0)] pub use ptr::{PtrExt, MutPtrExt}; pub use result::Result::{self, Ok, Err}; pub use slice::{AsSlice, SliceExt}; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 32123a8271ce4..f28c26d179845 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -262,6 +262,7 @@ pub unsafe fn write(dst: *mut T, src: T) { intrinsics::move_val_init(&mut *dst, src) } +#[cfg(stage0)] /// Methods on raw pointers #[stable(feature = "rust1", since = "1.0.0")] pub trait PtrExt { @@ -298,6 +299,7 @@ pub trait PtrExt { unsafe fn offset(self, count: isize) -> Self where Self::Target: Sized; } +#[cfg(stage0)] /// Methods on mutable raw pointers #[stable(feature = "rust1", since = "1.0.0")] pub trait MutPtrExt { @@ -317,6 +319,7 @@ pub trait MutPtrExt { unsafe fn as_mut<'a>(&self) -> Option<&'a mut Self::Target>; } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl PtrExt for *const T { type Target = T; @@ -344,6 +347,7 @@ impl PtrExt for *const T { } } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl PtrExt for *mut T { type Target = T; @@ -371,6 +375,7 @@ impl PtrExt for *mut T { } } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl MutPtrExt for *mut T { type Target = T; @@ -388,6 +393,119 @@ impl MutPtrExt for *mut T { } } +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +#[lang = "const_ptr"] +impl *const T { + /// Returns true if the pointer is null. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_null(self) -> bool { + self == 0 as *const T + } + + /// Returns `None` if the pointer is null, or else returns a reference to + /// the value wrapped in `Some`. + /// + /// # Safety + /// + /// While this method and its mutable counterpart are useful for + /// null-safety, it is important to note that this is still an unsafe + /// operation because the returned value could be pointing to invalid + /// memory. + #[unstable(feature = "core", + reason = "Option is not clearly the right return type, and we may want \ + to tie the return lifetime to a borrow of the raw pointer")] + #[inline] + pub unsafe fn as_ref<'a>(&self) -> Option<&'a T> { + if self.is_null() { + None + } else { + Some(&**self) + } + } + + /// Calculates the offset from a pointer. `count` is in units of T; e.g. a + /// `count` of 3 represents a pointer offset of `3 * sizeof::()` bytes. + /// + /// # Safety + /// + /// The offset must be in-bounds of the object, or one-byte-past-the-end. + /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether + /// the pointer is used. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn offset(self, count: isize) -> *const T where T: Sized { + intrinsics::offset(self, count) + } +} + +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +#[lang = "mut_ptr"] +impl *mut T { + /// Returns true if the pointer is null. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_null(self) -> bool { + self == 0 as *mut T + } + + /// Returns `None` if the pointer is null, or else returns a reference to + /// the value wrapped in `Some`. + /// + /// # Safety + /// + /// While this method and its mutable counterpart are useful for + /// null-safety, it is important to note that this is still an unsafe + /// operation because the returned value could be pointing to invalid + /// memory. + #[unstable(feature = "core", + reason = "Option is not clearly the right return type, and we may want \ + to tie the return lifetime to a borrow of the raw pointer")] + #[inline] + pub unsafe fn as_ref<'a>(&self) -> Option<&'a T> { + if self.is_null() { + None + } else { + Some(&**self) + } + } + + /// Calculates the offset from a pointer. `count` is in units of T; e.g. a + /// `count` of 3 represents a pointer offset of `3 * sizeof::()` bytes. + /// + /// # Safety + /// + /// The offset must be in-bounds of the object, or one-byte-past-the-end. + /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether + /// the pointer is used. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn offset(self, count: isize) -> *mut T where T: Sized { + intrinsics::offset(self, count) as *mut T + } + + /// Returns `None` if the pointer is null, or else returns a mutable + /// reference to the value wrapped in `Some`. + /// + /// # Safety + /// + /// As with `as_ref`, this is unsafe because it cannot verify the validity + /// of the returned pointer. + #[unstable(feature = "core", + reason = "return value does not necessarily convey all possible \ + information")] + #[inline] + pub unsafe fn as_mut<'a>(&self) -> Option<&'a mut T> { + if self.is_null() { + None + } else { + Some(&mut **self) + } + } +} + // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for *const T { diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 62cffa9b86e94..c8a8dd885018d 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -49,6 +49,7 @@ use option::Option::{None, Some}; use result::Result; use result::Result::{Ok, Err}; use ptr; +#[cfg(stage0)] use ptr::PtrExt; use mem; use mem::size_of; diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 6f72890d96fb5..3873f305b4234 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -30,6 +30,7 @@ use mem; use num::Int; use ops::{Fn, FnMut}; use option::Option::{self, None, Some}; +#[cfg(stage0)] use ptr::PtrExt; use raw::{Repr, Slice}; use result::Result::{self, Ok, Err}; diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 69fd0a57d5f38..7812363d55e72 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -24,7 +24,10 @@ use num::wrapping::{OverflowingOps, WrappingOps}; use ops::{Deref, DerefMut, Drop}; use option::Option; use option::Option::{Some, None}; +#[cfg(stage0)] use ptr::{self, PtrExt, Unique}; +#[cfg(not(stage0))] +use ptr::{self, Unique}; use rt::heap::{allocate, deallocate, EMPTY}; use collections::hash_state::HashState; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index c89edf7284293..72d014e77a780 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -20,6 +20,7 @@ use iter::Iterator; use marker::Sized; use ops::{Drop, FnOnce}; use option::Option::{self, Some, None}; +#[cfg(stage0)] use ptr::PtrExt; use result::Result::{Ok, Err}; use result; diff --git a/src/libstd/old_io/extensions.rs b/src/libstd/old_io/extensions.rs index b67ec847c79ae..a81275952c586 100644 --- a/src/libstd/old_io/extensions.rs +++ b/src/libstd/old_io/extensions.rs @@ -26,6 +26,7 @@ use num::Int; use ops::FnOnce; use option::Option; use option::Option::{Some, None}; +#[cfg(stage0)] use ptr::PtrExt; use result::Result::{Ok, Err}; #[cfg(stage0)] diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index 89e813de5b628..2c978177c5082 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -935,6 +935,7 @@ impl<'a> Reader for &'a mut (Reader+'a) { // API yet. If so, it should be a method on Vec. unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec, start: uint, end: uint) -> &'a mut [T] { use slice; + #[cfg(stage0)] use ptr::PtrExt; assert!(start <= end); diff --git a/src/libstd/os.rs b/src/libstd/os.rs index e04d7f3f240cb..fc05eb1d62703 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -52,6 +52,7 @@ use option::Option::{Some, None}; use option::Option; use old_path::{Path, GenericPath, BytesContainer}; use path::{self, PathBuf}; +#[cfg(stage0)] use ptr::PtrExt; use ptr; use result::Result::{Err, Ok}; diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index e21ae1657ee51..4327b26260ab6 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -40,6 +40,7 @@ #[doc(no_inline)] pub use iter::{Iterator, IteratorExt, Extend}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use option::Option::{self, Some, None}; +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/rt/at_exit_imp.rs b/src/libstd/rt/at_exit_imp.rs index 08755ba829f8f..f6bb87f011db1 100644 --- a/src/libstd/rt/at_exit_imp.rs +++ b/src/libstd/rt/at_exit_imp.rs @@ -12,6 +12,7 @@ //! //! Documentation can be found on the `rt::at_exit` function. +#[cfg(stage0)] use core::prelude::*; use boxed; From 3ff84fc5fdd9509fc3ee4595fd76aa31d4815b2a Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 10 Mar 2015 23:13:40 -0500 Subject: [PATCH 06/15] impl {i,u}{8,16,32,64,size} --- src/libarena/lib.rs | 1 + src/libcollections/btree/node.rs | 7 +- src/libcollections/vec.rs | 1 + src/libcollections/vec_deque.rs | 1 + src/libcore/num/mod.rs | 990 +++++++++++++++++++++++++++ src/librand/distributions/mod.rs | 2 +- src/libstd/collections/hash/map.rs | 1 + src/libstd/collections/hash/table.rs | 1 + src/libstd/num/mod.rs | 3 + 9 files changed, 1004 insertions(+), 3 deletions(-) diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index d08c9b3257a01..029d9d03835e8 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -46,6 +46,7 @@ use std::intrinsics::{TyDesc, get_tydesc}; use std::intrinsics; use std::marker; use std::mem; +#[cfg(stage0)] use std::num::{Int, UnsignedInt}; use std::ptr; use std::rc::Rc; diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index 1a8a4cb7e219e..006d6bb040e65 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -23,7 +23,7 @@ use core::iter::Zip; use core::marker::PhantomData; use core::ops::{Deref, DerefMut, Index, IndexMut}; use core::ptr::Unique; -use core::{slice, mem, ptr, cmp, num, raw}; +use core::{slice, mem, ptr, cmp, raw}; use alloc::heap::{self, EMPTY}; use borrow::Borrow; @@ -105,7 +105,10 @@ struct MutNodeSlice<'a, K: 'a, V: 'a> { /// Fails if `target_alignment` is not a power of two. #[inline] fn round_up_to_next(unrounded: usize, target_alignment: usize) -> usize { - assert!(num::UnsignedInt::is_power_of_two(target_alignment)); + #[cfg(stage0)] + use core::num::UnsignedInt; + + assert!(target_alignment.is_power_of_two()); (unrounded + target_alignment - 1) & !(target_alignment - 1) } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 937df5494dffa..82d68caeb3642 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -59,6 +59,7 @@ use core::intrinsics::assume; use core::iter::{repeat, FromIterator, IntoIterator}; use core::marker::PhantomData; use core::mem; +#[cfg(stage0)] use core::num::{Int, UnsignedInt}; use core::ops::{Index, IndexMut, Deref, Add}; use core::ops; diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 43c9edcaa2b28..65e44703df108 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -25,6 +25,7 @@ use core::default::Default; use core::fmt; use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator}; use core::mem; +#[cfg(stage0)] use core::num::{Int, UnsignedInt}; use core::num::wrapping::WrappingOps; use core::ops::{Index, IndexMut}; diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 6170092c8d107..4381b1fb3c907 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -708,6 +708,7 @@ signed_int_impl! { i32 } signed_int_impl! { i64 } signed_int_impl! { int } +#[cfg(stage0)] /// A built-in unsigned integer. #[stable(feature = "rust1", since = "1.0.0")] pub trait UnsignedInt: Int + WrappingOps { @@ -742,21 +743,1010 @@ pub trait UnsignedInt: Int + WrappingOps { } } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for uint {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u8 {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u16 {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u32 {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u64 {} +// NB(japaric) I added this module to avoid adding several `cfg(not(stage0))`, and avoid name +// clashes between macros. We should move all the items inside this module into the outer scope +// once the `Int` trait is removed +#[cfg(not(stage0))] +mod inherent { + use intrinsics; + use mem::size_of; + use option::Option::{self, Some, None}; + + use super::wrapping::{OverflowingOps, WrappingOps}; + + // `Int` + `SignedInt` implemented for signed integers + macro_rules! int_impl { + ($T:ty = $ActualT:ty, $UnsignedT:ty, $BITS:expr, + $add_with_overflow:path, + $sub_with_overflow:path, + $mul_with_overflow:path) => { + /// Returns the `0` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn zero() -> $T { 0 } + + /// Returns the `1` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn one() -> $T { 1 } + + /// Returns the smallest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn min_value() -> $T { (-1 as $T) << ($BITS - 1) } + + /// Returns the largest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn max_value() -> $T { let min: $T = <$T>::min_value(); !min } + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_zeros(), 5); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_zeros(self) -> u32 { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.leading_zeros(), 10); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn leading_zeros(self) -> u32 { (self as $UnsignedT).leading_zeros() } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn trailing_zeros(self) -> u32 { (self as $UnsignedT).trailing_zeros() } + + /// Shifts the bits to the left by a specified amount amount, `n`, wrapping + /// the truncated bits to the end of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0x3456789ABCDEF012u64; + /// + /// assert_eq!(n.rotate_left(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_left(self, n: u32) -> $T { (self as $UnsignedT).rotate_left(n) as $T } + + /// Shifts the bits to the right by a specified amount amount, `n`, wrapping + /// the truncated bits to the beginning of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xDEF0123456789ABCu64; + /// + /// assert_eq!(n.rotate_right(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_right(self, n: u32) -> $T { (self as $UnsignedT).rotate_right(n) as $T } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn swap_bytes(self) -> $T { (self as $UnsignedT).swap_bytes() as $T } + + /// Convert an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Int::from_be(n), n) + /// } else { + /// assert_eq!(Int::from_be(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_be(x: $T) -> $T { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } + + /// Convert an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Int::from_le(n), n) + /// } else { + /// assert_eq!(Int::from_le(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_le(x: $T) -> $T { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } + + /// Convert `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_be(self) -> $T { // or not to be? + if cfg!(target_endian = "big") { self } else { self.swap_bytes() } + } + + /// Convert `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_le(self) -> $T { + if cfg!(target_endian = "little") { self } else { self.swap_bytes() } + } + + /// Checked integer addition. Computes `self + other`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u16.checked_add(65530), Some(65535)); + /// assert_eq!(6u16.checked_add(65530), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_add(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $add_with_overflow, self, other) + } + + /// Checked integer subtraction. Computes `self - other`, returning `None` + /// if underflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_sub(1), Some(-128)); + /// assert_eq!((-128i8).checked_sub(1), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_sub(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $sub_with_overflow, self, other) + } + + /// Checked integer multiplication. Computes `self * other`, returning + /// `None` if underflow or overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u8.checked_mul(51), Some(255)); + /// assert_eq!(5u8.checked_mul(52), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_mul(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $mul_with_overflow, self, other) + } + + /// Checked integer division. Computes `self / other`, returning `None` if + /// `other == 0` or the operation results in underflow or overflow. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_div(-1), Some(127)); + /// assert_eq!((-128i8).checked_div(-1), None); + /// assert_eq!((1i8).checked_div(0), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_div(self, v: $T) -> Option<$T> { + match v { + 0 => None, + -1 if self == <$T>::min_value() + => None, + v => Some(self / v), + } + } + + /// Saturating integer addition. Computes `self + other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_add(self, other: $T) -> $T { + match self.checked_add(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::max_value(), + None => <$T>::min_value(), + } + } + + /// Saturating integer subtraction. Computes `self - other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_sub(self, other: $T) -> $T { + match self.checked_sub(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::min_value(), + None => <$T>::max_value(), + } + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(2.pow(4), 16); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn pow(self, mut exp: u32) -> $T { + let mut base = self; + let mut acc = <$T>::one(); + + let mut prev_base = self; + let mut base_oflo = false; + while exp > 0 { + if (exp & 1) == 1 { + if base_oflo { + // ensure overflow occurs in the same manner it + // would have otherwise (i.e. signal any exception + // it would have otherwise). + acc = acc * (prev_base * prev_base); + } else { + acc = acc * base; + } + } + prev_base = base; + let (new_base, new_base_oflo) = base.overflowing_mul(base); + base = new_base; + base_oflo = new_base_oflo; + exp /= 2; + } + acc + } + + /// Computes the absolute value of `self`. `Int::min_value()` will be + /// returned if the number is `Int::min_value()`. + #[unstable(feature = "core", reason = "overflow in debug builds?")] + #[inline] + pub fn abs(self) -> $T { + if self.is_negative() { -self } else { self } + } + + /// Returns a number representing sign of `self`. + /// + /// - `0` if the number is zero + /// - `1` if the number is positive + /// - `-1` if the number is negative + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn signum(self) -> $T { + match self { + n if n > 0 => 1, + 0 => 0, + _ => -1, + } + } + + /// Returns `true` if `self` is positive and `false` if the number + /// is zero or negative. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_positive(self) -> bool { self > 0 } + + /// Returns `true` if `self` is negative and `false` if the number + /// is zero or positive. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_negative(self) -> bool { self < 0 } + } + } + + #[lang = "i8"] + impl i8 { + int_impl! { i8 = i8, u8, 8, + intrinsics::i8_add_with_overflow, + intrinsics::i8_sub_with_overflow, + intrinsics::i8_mul_with_overflow } + } + + #[lang = "i16"] + impl i16 { + int_impl! { i16 = i16, u16, 16, + intrinsics::i16_add_with_overflow, + intrinsics::i16_sub_with_overflow, + intrinsics::i16_mul_with_overflow } + } + + #[lang = "i32"] + impl i32 { + int_impl! { i32 = i32, u32, 32, + intrinsics::i32_add_with_overflow, + intrinsics::i32_sub_with_overflow, + intrinsics::i32_mul_with_overflow } + } + + #[lang = "i64"] + impl i64 { + int_impl! { i64 = i64, u64, 64, + intrinsics::i64_add_with_overflow, + intrinsics::i64_sub_with_overflow, + intrinsics::i64_mul_with_overflow } + } + + #[cfg(target_pointer_width = "32")] + #[lang = "isize"] + impl isize { + int_impl! { int = i32, u32, 32, + intrinsics::i32_add_with_overflow, + intrinsics::i32_sub_with_overflow, + intrinsics::i32_mul_with_overflow } + } + + #[cfg(target_pointer_width = "64")] + #[lang = "isize"] + impl isize { + int_impl! { int = i64, u64, 64, + intrinsics::i64_add_with_overflow, + intrinsics::i64_sub_with_overflow, + intrinsics::i64_mul_with_overflow } + } + + // `Int` + `UnsignedInt` implemented for signed integers + macro_rules! uint_impl { + ($T:ty = $ActualT:ty, $BITS:expr, + $ctpop:path, + $ctlz:path, + $cttz:path, + $bswap:path, + $add_with_overflow:path, + $sub_with_overflow:path, + $mul_with_overflow:path) => { + /// Returns the `0` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn zero() -> $T { 0 } + + /// Returns the `1` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn one() -> $T { 1 } + + /// Returns the smallest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn min_value() -> $T { 0 } + + /// Returns the largest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn max_value() -> $T { -1 } + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_ones(self) -> u32 { unsafe { $ctpop(self as $ActualT) as u32 } } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_zeros(), 5); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_zeros(self) -> u32 { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.leading_zeros(), 10); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn leading_zeros(self) -> u32 { unsafe { $ctlz(self as $ActualT) as u32 } } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn trailing_zeros(self) -> u32 { unsafe { $cttz(self as $ActualT) as u32 } } + + /// Shifts the bits to the left by a specified amount amount, `n`, wrapping + /// the truncated bits to the end of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0x3456789ABCDEF012u64; + /// + /// assert_eq!(n.rotate_left(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_left(self, n: u32) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self << n) | (self >> (($BITS - n) % $BITS)) + } + + /// Shifts the bits to the right by a specified amount amount, `n`, wrapping + /// the truncated bits to the beginning of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xDEF0123456789ABCu64; + /// + /// assert_eq!(n.rotate_right(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_right(self, n: u32) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self >> n) | (self << (($BITS - n) % $BITS)) + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn swap_bytes(self) -> $T { unsafe { $bswap(self as $ActualT) as $T } } + + /// Convert an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Int::from_be(n), n) + /// } else { + /// assert_eq!(Int::from_be(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_be(x: $T) -> $T { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } + + /// Convert an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Int::from_le(n), n) + /// } else { + /// assert_eq!(Int::from_le(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_le(x: $T) -> $T { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } + + /// Convert `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_be(self) -> $T { // or not to be? + if cfg!(target_endian = "big") { self } else { self.swap_bytes() } + } + + /// Convert `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_le(self) -> $T { + if cfg!(target_endian = "little") { self } else { self.swap_bytes() } + } + + /// Checked integer addition. Computes `self + other`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u16.checked_add(65530), Some(65535)); + /// assert_eq!(6u16.checked_add(65530), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_add(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $add_with_overflow, self, other) + } + + /// Checked integer subtraction. Computes `self - other`, returning `None` + /// if underflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_sub(1), Some(-128)); + /// assert_eq!((-128i8).checked_sub(1), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_sub(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $sub_with_overflow, self, other) + } + + /// Checked integer multiplication. Computes `self * other`, returning + /// `None` if underflow or overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u8.checked_mul(51), Some(255)); + /// assert_eq!(5u8.checked_mul(52), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_mul(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $mul_with_overflow, self, other) + } + + /// Checked integer division. Computes `self / other`, returning `None` if + /// `other == 0` or the operation results in underflow or overflow. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_div(-1), Some(127)); + /// assert_eq!((-128i8).checked_div(-1), None); + /// assert_eq!((1i8).checked_div(0), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_div(self, v: $T) -> Option<$T> { + match v { + 0 => None, + v => Some(self / v), + } + } + + /// Saturating integer addition. Computes `self + other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_add(self, other: $T) -> $T { + match self.checked_add(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::max_value(), + None => <$T>::min_value(), + } + } + + /// Saturating integer subtraction. Computes `self - other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_sub(self, other: $T) -> $T { + match self.checked_sub(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::min_value(), + None => <$T>::max_value(), + } + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(2.pow(4), 16); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn pow(self, mut exp: u32) -> $T { + let mut base = self; + let mut acc = <$T>::one(); + + let mut prev_base = self; + let mut base_oflo = false; + while exp > 0 { + if (exp & 1) == 1 { + if base_oflo { + // ensure overflow occurs in the same manner it + // would have otherwise (i.e. signal any exception + // it would have otherwise). + acc = acc * (prev_base * prev_base); + } else { + acc = acc * base; + } + } + prev_base = base; + let (new_base, new_base_oflo) = base.overflowing_mul(base); + base = new_base; + base_oflo = new_base_oflo; + exp /= 2; + } + acc + } + + /// Returns `true` iff `self == 2^k` for some `k`. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_power_of_two(self) -> bool { + (self.wrapping_sub(<$T>::one())) & self == <$T>::zero() && !(self == <$T>::zero()) + } + + /// Returns the smallest power of two greater than or equal to `self`. + /// Unspecified behavior on overflow. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn next_power_of_two(self) -> $T { + let bits = size_of::<$T>() * 8; + let one: $T = <$T>::one(); + one << ((bits - self.wrapping_sub(one).leading_zeros() as usize) % bits) + } + + /// Returns the smallest power of two greater than or equal to `n`. If the + /// next power of two is greater than the type's maximum value, `None` is + /// returned, otherwise the power of two is wrapped in `Some`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn checked_next_power_of_two(self) -> Option<$T> { + let npot = self.next_power_of_two(); + if npot >= self { + Some(npot) + } else { + None + } + } + } + } + + /// Swapping a single byte is a no-op. This is marked as `unsafe` for + /// consistency with the other `bswap` intrinsics. + unsafe fn bswap8(x: u8) -> u8 { x } + + #[lang = "u8"] + impl u8 { + uint_impl! { u8 = u8, 8, + intrinsics::ctpop8, + intrinsics::ctlz8, + intrinsics::cttz8, + bswap8, + intrinsics::u8_add_with_overflow, + intrinsics::u8_sub_with_overflow, + intrinsics::u8_mul_with_overflow } + } + + #[lang = "u16"] + impl u16 { + uint_impl! { u16 = u16, 16, + intrinsics::ctpop16, + intrinsics::ctlz16, + intrinsics::cttz16, + intrinsics::bswap16, + intrinsics::u16_add_with_overflow, + intrinsics::u16_sub_with_overflow, + intrinsics::u16_mul_with_overflow } + } + + #[lang = "u32"] + impl u32 { + uint_impl! { u32 = u32, 32, + intrinsics::ctpop32, + intrinsics::ctlz32, + intrinsics::cttz32, + intrinsics::bswap32, + intrinsics::u32_add_with_overflow, + intrinsics::u32_sub_with_overflow, + intrinsics::u32_mul_with_overflow } + } + + + #[lang = "u64"] + impl u64 { + uint_impl! { u64 = u64, 64, + intrinsics::ctpop64, + intrinsics::ctlz64, + intrinsics::cttz64, + intrinsics::bswap64, + intrinsics::u64_add_with_overflow, + intrinsics::u64_sub_with_overflow, + intrinsics::u64_mul_with_overflow } + } + + #[cfg(target_pointer_width = "32")] + #[lang = "usize"] + impl usize { + uint_impl! { uint = u32, 32, + intrinsics::ctpop32, + intrinsics::ctlz32, + intrinsics::cttz32, + intrinsics::bswap32, + intrinsics::u32_add_with_overflow, + intrinsics::u32_sub_with_overflow, + intrinsics::u32_mul_with_overflow } + } + + #[cfg(target_pointer_width = "64")] + #[lang = "usize"] + impl usize { + uint_impl! { uint = u64, 64, + intrinsics::ctpop64, + intrinsics::ctlz64, + intrinsics::cttz64, + intrinsics::bswap64, + intrinsics::u64_add_with_overflow, + intrinsics::u64_sub_with_overflow, + intrinsics::u64_mul_with_overflow } + } +} + /// A generic trait for converting a value to a number. #[unstable(feature = "core", reason = "trait is likely to be removed")] pub trait ToPrimitive { diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index 79b176a4ffdcb..47bc2f5a11348 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -123,7 +123,7 @@ impl<'a, T: Clone> WeightedChoice<'a, T> { // strictly speaking, this is subsumed by the total weight == 0 case assert!(!items.is_empty(), "WeightedChoice::new called with no items"); - let mut running_total = 0; + let mut running_total = 0_usize; // we convert the list from individual weights to cumulative // weights so we can binary search. This *could* drop elements diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 0892365d9d5a5..6f8151c2b9f0a 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -23,6 +23,7 @@ use hash::{Hash, SipHasher}; use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map}; use marker::Sized; use mem::{self, replace}; +#[cfg(stage0)] use num::{Int, UnsignedInt}; use ops::{Deref, FnMut, Index, IndexMut}; use option::Option::{self, Some, None}; diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 7812363d55e72..cba46859f348e 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -19,6 +19,7 @@ use iter::{Iterator, IteratorExt, ExactSizeIterator, count}; use marker::{Copy, Send, Sync, Sized, self}; use mem::{min_align_of, size_of}; use mem; +#[cfg(stage0)] use num::{Int, UnsignedInt}; use num::wrapping::{OverflowingOps, WrappingOps}; use ops::{Deref, DerefMut, Drop}; diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 35d973d2d4e6d..599f3f02a8b76 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -23,7 +23,10 @@ use marker::Copy; use clone::Clone; use cmp::{PartialOrd, PartialEq}; +#[cfg(stage0)] pub use core::num::{Int, SignedInt, UnsignedInt}; +#[cfg(not(stage0))] +pub use core::num::{Int, SignedInt}; pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive}; pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64}; pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64}; From 6453fcd4ccaa84cf8a21b5991bae23a5923df98b Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 10 Mar 2015 23:58:16 -0500 Subject: [PATCH 07/15] extract libcollections tests into libcollectionstest --- mk/dist.mk | 1 + mk/tests.mk | 6 +- src/libcollections/binary_heap.rs | 215 --- src/libcollections/bit.rs | 1180 ------------ src/libcollections/btree/map.rs | 306 --- src/libcollections/btree/set.rs | 177 -- src/libcollections/enum_set.rs | 238 --- src/libcollections/fmt.rs | 12 - src/libcollections/lib.rs | 43 - src/libcollections/linked_list.rs | 569 ------ src/libcollections/slice.rs | 1630 ---------------- src/libcollections/str.rs | 1665 ---------------- src/libcollections/string.rs | 447 ----- src/libcollections/vec.rs | 988 ---------- src/libcollections/vec_deque.rs | 1118 ----------- src/libcollections/vec_map.rs | 507 ----- .../bench.rs | 4 +- src/libcollectionstest/binary_heap.rs | 219 +++ src/libcollectionstest/bit/mod.rs | 12 + src/libcollectionstest/bit/set.rs | 441 +++++ src/libcollectionstest/bit/vec.rs | 729 +++++++ src/libcollectionstest/btree/map.rs | 299 +++ src/libcollectionstest/btree/mod.rs | 12 + src/libcollectionstest/btree/set.rs | 180 ++ src/libcollectionstest/enum_set.rs | 240 +++ src/libcollectionstest/fmt.rs | 17 + src/libcollectionstest/lib.rs | 44 + src/libcollectionstest/linked_list.rs | 589 ++++++ src/libcollectionstest/slice.rs | 1627 ++++++++++++++++ src/libcollectionstest/str.rs | 1668 +++++++++++++++++ src/libcollectionstest/string.rs | 453 +++++ src/libcollectionstest/vec.rs | 994 ++++++++++ src/libcollectionstest/vec_deque.rs | 1150 ++++++++++++ src/libcollectionstest/vec_map.rs | 510 +++++ 34 files changed, 9192 insertions(+), 9098 deletions(-) rename src/{libcollections => libcollectionstest}/bench.rs (99%) create mode 100644 src/libcollectionstest/binary_heap.rs create mode 100644 src/libcollectionstest/bit/mod.rs create mode 100644 src/libcollectionstest/bit/set.rs create mode 100644 src/libcollectionstest/bit/vec.rs create mode 100644 src/libcollectionstest/btree/map.rs create mode 100644 src/libcollectionstest/btree/mod.rs create mode 100644 src/libcollectionstest/btree/set.rs create mode 100644 src/libcollectionstest/enum_set.rs create mode 100644 src/libcollectionstest/fmt.rs create mode 100644 src/libcollectionstest/lib.rs create mode 100644 src/libcollectionstest/linked_list.rs create mode 100644 src/libcollectionstest/slice.rs create mode 100644 src/libcollectionstest/str.rs create mode 100644 src/libcollectionstest/string.rs create mode 100644 src/libcollectionstest/vec.rs create mode 100644 src/libcollectionstest/vec_deque.rs create mode 100644 src/libcollectionstest/vec_map.rs diff --git a/mk/dist.mk b/mk/dist.mk index 831225556f3fc..57adaee51980b 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -53,6 +53,7 @@ PKG_FILES := \ driver \ etc \ $(foreach crate,$(CRATES),lib$(crate)) \ + libcollectionstest \ libcoretest \ libbacktrace \ rt \ diff --git a/mk/tests.mk b/mk/tests.mk index 48e50e47d4d1a..0851909a776e7 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -19,7 +19,11 @@ DEPS_coretest := $(eval $(call RUST_CRATE,coretest)) -TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) coretest +DEPS_collectionstest := +$(eval $(call RUST_CRATE,collectionstest)) + +TEST_TARGET_CRATES = $(filter-out collections core unicode,$(TARGET_CRATES)) \ + collectionstest coretest TEST_DOC_CRATES = $(DOC_CRATES) TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans rustc_lint,\ $(HOST_CRATES)) diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 4c57fdc46681b..11c8656c994b2 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -693,218 +693,3 @@ impl Extend for BinaryHeap { } } } - -#[cfg(test)] -mod tests { - use prelude::*; - - use super::BinaryHeap; - - #[test] - fn test_iterator() { - let data = vec![5, 9, 3]; - let iterout = [9, 5, 3]; - let heap = BinaryHeap::from_vec(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_vec(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_vec(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_vec(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_vec(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_vec(data); - while !heap.is_empty() { - assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); - assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); - } - } - - #[test] - fn test_push() { - let mut heap = BinaryHeap::from_vec(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::>::from_vec(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] - fn test_push_pop() { - let mut heap = BinaryHeap::from_vec(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] - fn test_replace() { - let mut heap = BinaryHeap::from_vec(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) { - let heap = BinaryHeap::from_vec(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::::new(); - assert!(heap.pop().is_none()); - } - - #[test] - fn test_empty_peek() { - let empty = BinaryHeap::::new(); - assert!(empty.peek().is_none()); - } - - #[test] - 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()); - } -} diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 7524fb6cf18a6..1dd463e0405ff 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -1903,1183 +1903,3 @@ impl<'a> IntoIterator for &'a BitSet { self.iter() } } - -#[cfg(test)] -mod tests { - use prelude::*; - use core::u32; - - use super::BitVec; - - #[test] - fn test_to_str() { - let zerolen = BitVec::new(); - assert_eq!(format!("{:?}", zerolen), ""); - - let eightbits = BitVec::from_elem(8, false); - assert_eq!(format!("{:?}", eightbits), "00000000") - } - - #[test] - fn test_0_elements() { - let act = BitVec::new(); - let exp = Vec::new(); - assert!(act.eq_vec(&exp)); - assert!(act.none() && act.all()); - } - - #[test] - fn test_1_element() { - let mut act = BitVec::from_elem(1, false); - assert!(act.eq_vec(&[false])); - assert!(act.none() && !act.all()); - act = BitVec::from_elem(1, true); - assert!(act.eq_vec(&[true])); - assert!(!act.none() && act.all()); - } - - #[test] - fn test_2_elements() { - let mut b = BitVec::from_elem(2, false); - b.set(0, true); - b.set(1, false); - assert_eq!(format!("{:?}", b), "10"); - assert!(!b.none() && !b.all()); - } - - #[test] - fn test_10_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(10, false); - assert!((act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false]))); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(10, true); - assert!((act.eq_vec(&[true, true, true, true, true, true, true, true, true, true]))); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(10, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - assert!((act.eq_vec(&[true, true, true, true, true, false, false, false, false, false]))); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(10, false); - act.set(5, true); - act.set(6, true); - act.set(7, true); - act.set(8, true); - act.set(9, true); - assert!((act.eq_vec(&[false, false, false, false, false, true, true, true, true, true]))); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(10, false); - act.set(0, true); - act.set(3, true); - act.set(6, true); - act.set(9, true); - assert!((act.eq_vec(&[true, false, false, true, false, false, true, false, false, true]))); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_31_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(31, false); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false])); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(31, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true])); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - act.set(5, true); - act.set(6, true); - act.set(7, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(16, true); - act.set(17, true); - act.set(18, true); - act.set(19, true); - act.set(20, true); - act.set(21, true); - act.set(22, true); - act.set(23, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(24, true); - act.set(25, true); - act.set(26, true); - act.set(27, true); - act.set(28, true); - act.set(29, true); - act.set(30, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, true, true, true, true, true, true, true])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(3, true); - act.set(17, true); - act.set(30, true); - assert!(act.eq_vec( - &[false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true])); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_32_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(32, false); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false])); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(32, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true])); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - act.set(5, true); - act.set(6, true); - act.set(7, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(16, true); - act.set(17, true); - act.set(18, true); - act.set(19, true); - act.set(20, true); - act.set(21, true); - act.set(22, true); - act.set(23, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(24, true); - act.set(25, true); - act.set(26, true); - act.set(27, true); - act.set(28, true); - act.set(29, true); - act.set(30, true); - act.set(31, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, true, true, true, true, true, true, true, true])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(3, true); - act.set(17, true); - act.set(30, true); - act.set(31, true); - assert!(act.eq_vec( - &[false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true, true])); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_33_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(33, false); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false])); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(33, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true])); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - act.set(5, true); - act.set(6, true); - act.set(7, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(16, true); - act.set(17, true); - act.set(18, true); - act.set(19, true); - act.set(20, true); - act.set(21, true); - act.set(22, true); - act.set(23, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(24, true); - act.set(25, true); - act.set(26, true); - act.set(27, true); - act.set(28, true); - act.set(29, true); - act.set(30, true); - act.set(31, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, true, true, true, true, true, true, true, true, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(3, true); - act.set(17, true); - act.set(30, true); - act.set(31, true); - act.set(32, true); - assert!(act.eq_vec( - &[false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true, true, true])); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_equal_differing_sizes() { - let v0 = BitVec::from_elem(10, false); - let v1 = BitVec::from_elem(11, false); - assert!(v0 != v1); - } - - #[test] - fn test_equal_greatly_differing_sizes() { - let v0 = BitVec::from_elem(10, false); - let v1 = BitVec::from_elem(110, false); - assert!(v0 != v1); - } - - #[test] - fn test_equal_sneaky_small() { - let mut a = BitVec::from_elem(1, false); - a.set(0, true); - - let mut b = BitVec::from_elem(1, true); - b.set(0, true); - - assert_eq!(a, b); - } - - #[test] - fn test_equal_sneaky_big() { - let mut a = BitVec::from_elem(100, false); - for i in 0..100 { - a.set(i, true); - } - - let mut b = BitVec::from_elem(100, true); - for i in 0..100 { - b.set(i, true); - } - - assert_eq!(a, b); - } - - #[test] - fn test_from_bytes() { - let bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); - let str = concat!("10110110", "00000000", "11111111"); - assert_eq!(format!("{:?}", bit_vec), str); - } - - #[test] - fn test_to_bytes() { - let mut bv = BitVec::from_elem(3, true); - bv.set(1, false); - assert_eq!(bv.to_bytes(), [0b10100000]); - - let mut bv = BitVec::from_elem(9, false); - bv.set(2, true); - bv.set(8, true); - assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]); - } - - #[test] - fn test_from_bools() { - let bools = vec![true, false, true, true]; - let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); - assert_eq!(format!("{:?}", bit_vec), "1011"); - } - - #[test] - fn test_to_bools() { - let bools = vec![false, false, true, false, false, true, true, false]; - assert_eq!(BitVec::from_bytes(&[0b00100110]).iter().collect::>(), bools); - } - - #[test] - fn test_bit_vec_iterator() { - let bools = vec![true, false, true, true]; - let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); - - assert_eq!(bit_vec.iter().collect::>(), bools); - - let long: Vec<_> = (0..10000).map(|i| i % 2 == 0).collect(); - let bit_vec: BitVec = long.iter().map(|n| *n).collect(); - assert_eq!(bit_vec.iter().collect::>(), long) - } - - #[test] - fn test_small_difference() { - let mut b1 = BitVec::from_elem(3, false); - let mut b2 = BitVec::from_elem(3, false); - b1.set(0, true); - b1.set(1, true); - b2.set(1, true); - b2.set(2, true); - assert!(b1.difference(&b2)); - assert!(b1[0]); - assert!(!b1[1]); - assert!(!b1[2]); - } - - #[test] - fn test_big_difference() { - let mut b1 = BitVec::from_elem(100, false); - let mut b2 = BitVec::from_elem(100, false); - b1.set(0, true); - b1.set(40, true); - b2.set(40, true); - b2.set(80, true); - assert!(b1.difference(&b2)); - assert!(b1[0]); - assert!(!b1[40]); - assert!(!b1[80]); - } - - #[test] - fn test_small_clear() { - let mut b = BitVec::from_elem(14, true); - assert!(!b.none() && b.all()); - b.clear(); - assert!(b.none() && !b.all()); - } - - #[test] - fn test_big_clear() { - let mut b = BitVec::from_elem(140, true); - assert!(!b.none() && b.all()); - b.clear(); - assert!(b.none() && !b.all()); - } - - #[test] - fn test_bit_vec_lt() { - let mut a = BitVec::from_elem(5, false); - let mut b = BitVec::from_elem(5, false); - - assert!(!(a < b) && !(b < a)); - b.set(2, true); - assert!(a < b); - a.set(3, true); - assert!(a < b); - a.set(2, true); - assert!(!(a < b) && b < a); - b.set(0, true); - assert!(a < b); - } - - #[test] - fn test_ord() { - let mut a = BitVec::from_elem(5, false); - let mut b = BitVec::from_elem(5, false); - - assert!(a <= b && a >= b); - a.set(1, true); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - b.set(1, true); - b.set(2, true); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } - - - #[test] - fn test_small_bit_vec_tests() { - let v = BitVec::from_bytes(&[0]); - assert!(!v.all()); - assert!(!v.any()); - assert!(v.none()); - - let v = BitVec::from_bytes(&[0b00010100]); - assert!(!v.all()); - assert!(v.any()); - assert!(!v.none()); - - let v = BitVec::from_bytes(&[0xFF]); - assert!(v.all()); - assert!(v.any()); - assert!(!v.none()); - } - - #[test] - fn test_big_bit_vec_tests() { - let v = BitVec::from_bytes(&[ // 88 bits - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0]); - assert!(!v.all()); - assert!(!v.any()); - assert!(v.none()); - - let v = BitVec::from_bytes(&[ // 88 bits - 0, 0, 0b00010100, 0, - 0, 0, 0, 0b00110100, - 0, 0, 0]); - assert!(!v.all()); - assert!(v.any()); - assert!(!v.none()); - - let v = BitVec::from_bytes(&[ // 88 bits - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF]); - assert!(v.all()); - assert!(v.any()); - assert!(!v.none()); - } - - #[test] - fn test_bit_vec_push_pop() { - let mut s = BitVec::from_elem(5 * u32::BITS as usize - 2, false); - assert_eq!(s.len(), 5 * u32::BITS as usize - 2); - assert_eq!(s[5 * u32::BITS as usize - 3], false); - s.push(true); - s.push(true); - assert_eq!(s[5 * u32::BITS as usize - 2], true); - assert_eq!(s[5 * u32::BITS as usize - 1], true); - // Here the internal vector will need to be extended - s.push(false); - assert_eq!(s[5 * u32::BITS as usize], false); - s.push(false); - assert_eq!(s[5 * u32::BITS as usize + 1], false); - assert_eq!(s.len(), 5 * u32::BITS as usize + 2); - // Pop it all off - assert_eq!(s.pop(), Some(false)); - assert_eq!(s.pop(), Some(false)); - assert_eq!(s.pop(), Some(true)); - assert_eq!(s.pop(), Some(true)); - assert_eq!(s.len(), 5 * u32::BITS as usize - 2); - } - - #[test] - fn test_bit_vec_truncate() { - let mut s = BitVec::from_elem(5 * u32::BITS as usize, true); - - assert_eq!(s, BitVec::from_elem(5 * u32::BITS as usize, true)); - assert_eq!(s.len(), 5 * u32::BITS as usize); - s.truncate(4 * u32::BITS as usize); - assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true)); - assert_eq!(s.len(), 4 * u32::BITS as usize); - // Truncating to a size > s.len() should be a noop - s.truncate(5 * u32::BITS as usize); - assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true)); - assert_eq!(s.len(), 4 * u32::BITS as usize); - s.truncate(3 * u32::BITS as usize - 10); - assert_eq!(s, BitVec::from_elem(3 * u32::BITS as usize - 10, true)); - assert_eq!(s.len(), 3 * u32::BITS as usize - 10); - s.truncate(0); - assert_eq!(s, BitVec::from_elem(0, true)); - assert_eq!(s.len(), 0); - } - - #[test] - fn test_bit_vec_reserve() { - let mut s = BitVec::from_elem(5 * u32::BITS as usize, true); - // Check capacity - assert!(s.capacity() >= 5 * u32::BITS as usize); - s.reserve(2 * u32::BITS as usize); - assert!(s.capacity() >= 7 * u32::BITS as usize); - s.reserve(7 * u32::BITS as usize); - assert!(s.capacity() >= 12 * u32::BITS as usize); - s.reserve_exact(7 * u32::BITS as usize); - assert!(s.capacity() >= 12 * u32::BITS as usize); - s.reserve(7 * u32::BITS as usize + 1); - assert!(s.capacity() >= 12 * u32::BITS as usize + 1); - // Check that length hasn't changed - assert_eq!(s.len(), 5 * u32::BITS as usize); - s.push(true); - s.push(false); - s.push(true); - assert_eq!(s[5 * u32::BITS as usize - 1], true); - assert_eq!(s[5 * u32::BITS as usize - 0], true); - assert_eq!(s[5 * u32::BITS as usize + 1], false); - assert_eq!(s[5 * u32::BITS as usize + 2], true); - } - - #[test] - fn test_bit_vec_grow() { - let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010]); - bit_vec.grow(32, true); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF])); - bit_vec.grow(64, false); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])); - bit_vec.grow(16, true); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF])); - } - - #[test] - fn test_bit_vec_extend() { - let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); - let ext = BitVec::from_bytes(&[0b01001001, 0b10010010, 0b10111101]); - bit_vec.extend(ext.iter()); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111, - 0b01001001, 0b10010010, 0b10111101])); - } -} - - - - -#[cfg(test)] -mod bit_vec_bench { - use std::prelude::v1::*; - use std::rand; - use std::rand::Rng; - use std::u32; - use test::{Bencher, black_box}; - - use super::BitVec; - - const BENCH_BITS : usize = 1 << 14; - - fn rng() -> rand::IsaacRng { - let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; - rand::SeedableRng::from_seed(seed) - } - - #[bench] - fn bench_usize_small(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = 0 as usize; - b.iter(|| { - for _ in 0..100 { - bit_vec |= 1 << ((r.next_u32() as usize) % u32::BITS as usize); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_set_big_fixed(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - for _ in 0..100 { - bit_vec.set((r.next_u32() as usize) % BENCH_BITS, true); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_set_big_variable(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - for _ in 0..100 { - bit_vec.set((r.next_u32() as usize) % BENCH_BITS, r.gen()); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_set_small(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitVec::from_elem(u32::BITS as usize, false); - b.iter(|| { - for _ in 0..100 { - bit_vec.set((r.next_u32() as usize) % u32::BITS as usize, true); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_vec_big_union(b: &mut Bencher) { - let mut b1 = BitVec::from_elem(BENCH_BITS, false); - let b2 = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - b1.union(&b2) - }) - } - - #[bench] - fn bench_bit_vec_small_iter(b: &mut Bencher) { - let bit_vec = BitVec::from_elem(u32::BITS as usize, false); - b.iter(|| { - let mut sum = 0; - for _ in 0..10 { - for pres in &bit_vec { - sum += pres as usize; - } - } - sum - }) - } - - #[bench] - fn bench_bit_vec_big_iter(b: &mut Bencher) { - let bit_vec = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - let mut sum = 0; - for pres in &bit_vec { - sum += pres as usize; - } - sum - }) - } -} - - - - - - - -#[cfg(test)] -mod bit_set_test { - use prelude::*; - use std::iter::range_step; - - use super::{BitVec, BitSet}; - - #[test] - fn test_bit_set_show() { - let mut s = BitSet::new(); - s.insert(1); - s.insert(10); - s.insert(50); - s.insert(2); - assert_eq!("{1, 2, 10, 50}", format!("{:?}", s)); - } - - #[test] - fn test_bit_set_from_usizes() { - let usizes = vec![0, 2, 2, 3]; - let a: BitSet = usizes.into_iter().collect(); - let mut b = BitSet::new(); - b.insert(0); - b.insert(2); - b.insert(3); - assert_eq!(a, b); - } - - #[test] - fn test_bit_set_iterator() { - let usizes = vec![0, 2, 2, 3]; - let bit_vec: BitSet = usizes.into_iter().collect(); - - let idxs: Vec<_> = bit_vec.iter().collect(); - assert_eq!(idxs, [0, 2, 3]); - - let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect(); - let real: Vec<_> = range_step(0, 10000, 2).collect(); - - let idxs: Vec<_> = long.iter().collect(); - assert_eq!(idxs, real); - } - - #[test] - fn test_bit_set_frombit_vec_init() { - let bools = [true, false]; - let lengths = [10, 64, 100]; - for &b in &bools { - for &l in &lengths { - let bitset = BitSet::from_bit_vec(BitVec::from_elem(l, b)); - assert_eq!(bitset.contains(&1), b); - assert_eq!(bitset.contains(&(l-1)), b); - assert!(!bitset.contains(&l)); - } - } - } - - #[test] - fn test_bit_vec_masking() { - let b = BitVec::from_elem(140, true); - let mut bs = BitSet::from_bit_vec(b); - assert!(bs.contains(&139)); - assert!(!bs.contains(&140)); - assert!(bs.insert(150)); - assert!(!bs.contains(&140)); - assert!(!bs.contains(&149)); - assert!(bs.contains(&150)); - assert!(!bs.contains(&151)); - } - - #[test] - fn test_bit_set_basic() { - let mut b = BitSet::new(); - assert!(b.insert(3)); - assert!(!b.insert(3)); - assert!(b.contains(&3)); - assert!(b.insert(4)); - assert!(!b.insert(4)); - assert!(b.contains(&3)); - assert!(b.insert(400)); - assert!(!b.insert(400)); - assert!(b.contains(&400)); - assert_eq!(b.len(), 3); - } - - #[test] - fn test_bit_set_intersection() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - - assert!(a.insert(11)); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(77)); - assert!(a.insert(103)); - assert!(a.insert(5)); - - assert!(b.insert(2)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(5)); - assert!(b.insert(3)); - - let expected = [3, 5, 11, 77]; - let actual: Vec<_> = a.intersection(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_difference() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(200)); - assert!(a.insert(500)); - - assert!(b.insert(3)); - assert!(b.insert(200)); - - let expected = [1, 5, 500]; - let actual: Vec<_> = a.difference(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_symmetric_difference() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(3)); - assert!(b.insert(9)); - assert!(b.insert(14)); - assert!(b.insert(220)); - - let expected = [1, 5, 11, 14, 220]; - let actual: Vec<_> = a.symmetric_difference(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_union() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - assert!(a.insert(160)); - assert!(a.insert(19)); - assert!(a.insert(24)); - assert!(a.insert(200)); - - assert!(b.insert(1)); - assert!(b.insert(5)); - assert!(b.insert(9)); - assert!(b.insert(13)); - assert!(b.insert(19)); - - let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160, 200]; - let actual: Vec<_> = a.union(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_subset() { - let mut set1 = BitSet::new(); - let mut set2 = BitSet::new(); - - assert!(set1.is_subset(&set2)); // {} {} - set2.insert(100); - assert!(set1.is_subset(&set2)); // {} { 1 } - set2.insert(200); - assert!(set1.is_subset(&set2)); // {} { 1, 2 } - set1.insert(200); - assert!(set1.is_subset(&set2)); // { 2 } { 1, 2 } - set1.insert(300); - assert!(!set1.is_subset(&set2)); // { 2, 3 } { 1, 2 } - set2.insert(300); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3 } - set2.insert(400); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3, 4 } - set2.remove(&100); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 2, 3, 4 } - set2.remove(&300); - assert!(!set1.is_subset(&set2)); // { 2, 3 } { 2, 4 } - set1.remove(&300); - assert!(set1.is_subset(&set2)); // { 2 } { 2, 4 } - } - - #[test] - fn test_bit_set_is_disjoint() { - let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01000000])); - let c = BitSet::new(); - let d = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00110000])); - - assert!(!a.is_disjoint(&d)); - assert!(!d.is_disjoint(&a)); - - assert!(a.is_disjoint(&b)); - assert!(a.is_disjoint(&c)); - assert!(b.is_disjoint(&a)); - assert!(b.is_disjoint(&c)); - assert!(c.is_disjoint(&a)); - assert!(c.is_disjoint(&b)); - } - - #[test] - fn test_bit_set_union_with() { - //a should grow to include larger elements - let mut a = BitSet::new(); - a.insert(0); - let mut b = BitSet::new(); - b.insert(5); - let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); - a.union_with(&b); - assert_eq!(a, expected); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); - let c = a.clone(); - a.union_with(&b); - b.union_with(&c); - assert_eq!(a.len(), 4); - assert_eq!(b.len(), 4); - } - - #[test] - fn test_bit_set_intersect_with() { - // Explicitly 0'ed bits - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert!(a.is_empty()); - assert!(b.is_empty()); - - // Uninitialized bits should behave like 0's - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::new(); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert!(a.is_empty()); - assert!(b.is_empty()); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert_eq!(a.len(), 2); - assert_eq!(b.len(), 2); - } - - #[test] - fn test_bit_set_difference_with() { - // Explicitly 0'ed bits - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - a.difference_with(&b); - assert!(a.is_empty()); - - // Uninitialized bits should behave like 0's - let mut a = BitSet::new(); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11111111])); - a.difference_with(&b); - assert!(a.is_empty()); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); - let c = a.clone(); - a.difference_with(&b); - b.difference_with(&c); - assert_eq!(a.len(), 1); - assert_eq!(b.len(), 1); - } - - #[test] - fn test_bit_set_symmetric_difference_with() { - //a should grow to include larger elements - let mut a = BitSet::new(); - a.insert(0); - a.insert(1); - let mut b = BitSet::new(); - b.insert(1); - b.insert(5); - let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); - a.symmetric_difference_with(&b); - assert_eq!(a, expected); - - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::new(); - let c = a.clone(); - a.symmetric_difference_with(&b); - assert_eq!(a, c); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101010])); - let c = a.clone(); - a.symmetric_difference_with(&b); - b.symmetric_difference_with(&c); - assert_eq!(a.len(), 2); - assert_eq!(b.len(), 2); - } - - #[test] - fn test_bit_set_eq() { - let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let c = BitSet::new(); - - assert!(a == a); - assert!(a != b); - assert!(a != c); - assert!(b == b); - assert!(b == c); - assert!(c == c); - } - - #[test] - fn test_bit_set_cmp() { - let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let c = BitSet::new(); - - assert_eq!(a.cmp(&b), Greater); - assert_eq!(a.cmp(&c), Greater); - assert_eq!(b.cmp(&a), Less); - assert_eq!(b.cmp(&c), Equal); - assert_eq!(c.cmp(&a), Less); - assert_eq!(c.cmp(&b), Equal); - } - - #[test] - fn test_bit_vec_remove() { - let mut a = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.remove(&1)); - - assert!(a.insert(100)); - assert!(a.remove(&100)); - - assert!(a.insert(1000)); - assert!(a.remove(&1000)); - a.shrink_to_fit(); - } - - #[test] - fn test_bit_vec_clone() { - let mut a = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(100)); - assert!(a.insert(1000)); - - let mut b = a.clone(); - - assert!(a == b); - - assert!(b.remove(&1)); - assert!(a.contains(&1)); - - assert!(a.remove(&1000)); - assert!(b.contains(&1000)); - } -} - - - - - -#[cfg(test)] -mod bit_set_bench { - use std::prelude::v1::*; - use std::rand; - use std::rand::Rng; - use std::u32; - use test::{Bencher, black_box}; - - use super::{BitVec, BitSet}; - - const BENCH_BITS : usize = 1 << 14; - - fn rng() -> rand::IsaacRng { - let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; - rand::SeedableRng::from_seed(seed) - } - - #[bench] - fn bench_bit_vecset_small(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitSet::new(); - b.iter(|| { - for _ in 0..100 { - bit_vec.insert((r.next_u32() as usize) % u32::BITS as usize); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_vecset_big(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitSet::new(); - b.iter(|| { - for _ in 0..100 { - bit_vec.insert((r.next_u32() as usize) % BENCH_BITS); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_vecset_iter(b: &mut Bencher) { - let bit_vec = BitSet::from_bit_vec(BitVec::from_fn(BENCH_BITS, - |idx| {idx % 3 == 0})); - b.iter(|| { - let mut sum = 0; - for idx in &bit_vec { - sum += idx as usize; - } - sum - }) - } -} diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index f2d94709c9a32..c7e1e3c91766e 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -1599,309 +1599,3 @@ impl BTreeMap { } } } - - - - - -#[cfg(test)] -mod test { - use prelude::*; - use std::iter::range_inclusive; - - use super::BTreeMap; - use super::Entry::{Occupied, Vacant}; - use Bound::{self, Included, Excluded, Unbounded}; - - #[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(size: usize, mut iter: T) where T: Iterator { - 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(size: usize, mut iter: T) where T: Iterator { - 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_iter_mixed() { - let size = 10000; - - // Forwards - let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test(size: usize, mut iter: T) - where T: Iterator + 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(Included(&2), Unbounded).zip(2..size) { - assert_eq!(k, i); - assert_eq!(v, i); - j += 1; - } - assert_eq!(j, size - 2); - } - - #[test] - fn test_range_1000() { - let size = 1000; - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test(map: &BTreeMap, 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() { - 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 = range_inclusive(i, j).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_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); - } -} - - - - - - -#[cfg(test)] -mod bench { - use prelude::*; - use std::rand::{weak_rng, Rng}; - use test::{Bencher, black_box}; - - use super::BTreeMap; - - map_insert_rand_bench!{insert_rand_100, 100, BTreeMap} - map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap} - - map_insert_seq_bench!{insert_seq_100, 100, BTreeMap} - map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap} - - map_find_rand_bench!{find_rand_100, 100, BTreeMap} - map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap} - - map_find_seq_bench!{find_seq_100, 100, BTreeMap} - map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap} - - fn bench_iter(b: &mut Bencher, size: i32) { - let mut map = BTreeMap::::new(); - let mut rng = weak_rng(); - - for _ in 0..size { - map.insert(rng.gen(), rng.gen()); - } - - b.iter(|| { - for entry in &map { - black_box(entry); - } - }); - } - - #[bench] - pub fn iter_20(b: &mut Bencher) { - bench_iter(b, 20); - } - - #[bench] - pub fn iter_1000(b: &mut Bencher) { - bench_iter(b, 1000); - } - - #[bench] - pub fn iter_100000(b: &mut Bencher) { - bench_iter(b, 100000); - } -} diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index a5ef36bcdab7a..5616d36ce0ba9 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -742,180 +742,3 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { } } } - - -#[cfg(test)] -mod test { - use prelude::*; - - use super::BTreeSet; - use std::hash::{self, SipHasher}; - - #[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::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); - } - - struct Counter<'a, 'b> { - i: &'a mut usize, - expected: &'b [i32], - } - - impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> { - type Output = bool; - - extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool { - assert_eq!(x, self.expected[*self.i]); - *self.i += 1; - true - } - } - - fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) where - // FIXME Replace Counter with `Box _>` - F: FnOnce(&BTreeSet, &BTreeSet, Counter) -> 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, Counter { i: &mut i, expected: expected }); - 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.iter()); - - // FIXME: #5801: this needs a type hint to compile... - let result: Option<(&usize, & &'static str)> = z.next(); - assert_eq!(result.unwrap(), (&5, &("bar"))); - - let result: Option<(&usize, & &'static str)> = z.next(); - assert_eq!(result.unwrap(), (&11, &("foo"))); - - let result: Option<(&usize, & &'static str)> = z.next(); - assert!(result.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::::new(); - - set.insert(1); - set.insert(2); - - let set_str = format!("{:?}", set); - - assert_eq!(set_str, "{1, 2}"); - assert_eq!(format!("{:?}", empty), "{}"); - } -} diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index eec61cfcd5624..fe2efc7164d0c 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -285,241 +285,3 @@ impl Extend for EnumSet { } } } - -#[cfg(test)] -mod test { - use self::Foo::*; - use prelude::*; - use core::mem; - - use super::{EnumSet, CLike}; - - #[derive(Copy, PartialEq, Debug)] - #[repr(usize)] - enum Foo { - A, B, C - } - - impl CLike for Foo { - fn to_usize(&self) -> usize { - *self as usize - } - - fn from_usize(v: usize) -> Foo { - unsafe { mem::transmute(v) } - } - } - - #[test] - fn test_new() { - let e: EnumSet = EnumSet::new(); - assert!(e.is_empty()); - } - - #[test] - fn test_show() { - let mut e = EnumSet::new(); - assert!(format!("{:?}", e) == "{}"); - e.insert(A); - assert!(format!("{:?}", e) == "{A}"); - e.insert(C); - assert!(format!("{:?}", e) == "{A, C}"); - } - - #[test] - fn test_len() { - let mut e = EnumSet::new(); - assert_eq!(e.len(), 0); - e.insert(A); - e.insert(B); - e.insert(C); - assert_eq!(e.len(), 3); - e.remove(&A); - assert_eq!(e.len(), 2); - e.clear(); - assert_eq!(e.len(), 0); - } - - /////////////////////////////////////////////////////////////////////////// - // intersect - - #[test] - fn test_two_empties_do_not_intersect() { - let e1: EnumSet = EnumSet::new(); - let e2: EnumSet = EnumSet::new(); - assert!(e1.is_disjoint(&e2)); - } - - #[test] - fn test_empty_does_not_intersect_with_full() { - let e1: EnumSet = EnumSet::new(); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - e2.insert(C); - - assert!(e1.is_disjoint(&e2)); - } - - #[test] - fn test_disjoint_intersects() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(B); - - assert!(e1.is_disjoint(&e2)); - } - - #[test] - fn test_overlapping_intersects() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - - assert!(!e1.is_disjoint(&e2)); - } - - /////////////////////////////////////////////////////////////////////////// - // contains and contains_elem - - #[test] - fn test_superset() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - - let mut e3: EnumSet = EnumSet::new(); - e3.insert(C); - - assert!(e1.is_subset(&e2)); - assert!(e2.is_superset(&e1)); - assert!(!e3.is_superset(&e2)); - assert!(!e2.is_superset(&e3)) - } - - #[test] - fn test_contains() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - assert!(e1.contains(&A)); - assert!(!e1.contains(&B)); - assert!(!e1.contains(&C)); - - e1.insert(A); - e1.insert(B); - assert!(e1.contains(&A)); - assert!(e1.contains(&B)); - assert!(!e1.contains(&C)); - } - - /////////////////////////////////////////////////////////////////////////// - // iter - - #[test] - fn test_iterator() { - let mut e1: EnumSet = EnumSet::new(); - - let elems: ::vec::Vec = e1.iter().collect(); - assert!(elems.is_empty()); - - e1.insert(A); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!([A], elems); - - e1.insert(C); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!([A,C], elems); - - e1.insert(C); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!([A,C], elems); - - e1.insert(B); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!([A,B,C], elems); - } - - /////////////////////////////////////////////////////////////////////////// - // operators - - #[test] - fn test_operators() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - e1.insert(C); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(B); - e2.insert(C); - - let e_union = e1 | e2; - let elems: ::vec::Vec<_> = e_union.iter().collect(); - assert_eq!([A,B,C], elems); - - let e_intersection = e1 & e2; - let elems: ::vec::Vec<_> = e_intersection.iter().collect(); - assert_eq!([C], elems); - - // Another way to express intersection - let e_intersection = e1 - (e1 - e2); - let elems: ::vec::Vec<_> = e_intersection.iter().collect(); - assert_eq!([C], elems); - - let e_subtract = e1 - e2; - let elems: ::vec::Vec<_> = e_subtract.iter().collect(); - assert_eq!([A], elems); - - // Bitwise XOR of two sets, aka symmetric difference - let e_symmetric_diff = e1 ^ e2; - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!([A,B], elems); - - // Another way to express symmetric difference - let e_symmetric_diff = (e1 - e2) | (e2 - e1); - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!([A,B], elems); - - // Yet another way to express symmetric difference - let e_symmetric_diff = (e1 | e2) - (e1 & e2); - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!([A,B], elems); - } - - #[test] - #[should_panic] - fn test_overflow() { - #[allow(dead_code)] - #[derive(Copy)] - #[repr(usize)] - enum Bar { - V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, - V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, - V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, - V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, - V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, - V50, V51, V52, V53, V54, V55, V56, V57, V58, V59, - V60, V61, V62, V63, V64, V65, V66, V67, V68, V69, - } - - impl CLike for Bar { - fn to_usize(&self) -> usize { - *self as usize - } - - fn from_usize(v: usize) -> Bar { - unsafe { mem::transmute(v) } - } - } - let mut set = EnumSet::new(); - set.insert(Bar::V64); - } -} diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index 5d35c3902a31a..bb7db1151e833 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -434,15 +434,3 @@ pub fn format(args: Arguments) -> string::String { let _ = write!(&mut output, "{}", args); output } - -#[cfg(test)] -mod tests { - use prelude::*; - use fmt; - - #[test] - fn test_format() { - let s = fmt::format(format_args!("Hello, {}!", "world")); - assert_eq!(s.as_slice(), "Hello, world!"); - } -} diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 3a2fc17e1e985..0d53215a59659 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -47,10 +47,6 @@ extern crate core; extern crate unicode; extern crate alloc; -#[cfg(test)] extern crate test; -#[cfg(test)] #[macro_use] extern crate std; -#[cfg(test)] #[macro_use] extern crate log; - pub use binary_heap::BinaryHeap; pub use bit_vec::BitVec; pub use bit_set::BitSet; @@ -85,8 +81,6 @@ pub use alloc::boxed; #[macro_use] mod macros; -#[cfg(test)] #[macro_use] mod bench; - pub mod binary_heap; mod bit; mod btree; @@ -137,47 +131,10 @@ pub mod btree_set { #[doc(hidden)] pub fn fixme_14344_be_sure_to_link_to_collections() {} -#[cfg(not(test))] mod std { pub use core::ops; // RangeFull } -#[cfg(test)] -mod prelude { - // from core. - pub use core::clone::Clone; - pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord}; - pub use core::cmp::Ordering::{Less, Equal, Greater}; - pub use core::iter::range; - pub use core::iter::{FromIterator, Extend, IteratorExt}; - pub use core::iter::{Iterator, DoubleEndedIterator, RandomAccessIterator}; - pub use core::iter::{ExactSizeIterator}; - pub use core::marker::{Copy, Send, Sized, Sync}; - pub use core::mem::drop; - pub use core::ops::{Drop, Fn, FnMut, FnOnce}; - pub use core::option::Option; - pub use core::option::Option::{Some, None}; - pub use core::ptr::PtrExt; - pub use core::result::Result; - pub use core::result::Result::{Ok, Err}; - - // in core and collections (may differ). - pub use slice::{AsSlice, SliceExt}; - #[cfg(stage0)] - pub use str::{Str, StrExt}; - #[cfg(not(stage0))] - pub use str::Str; - - // from other crates. - pub use alloc::boxed::Box; - - // from collections. - pub use borrow::IntoCow; - pub use slice::SliceConcatExt; - pub use string::{String, ToString}; - pub use vec::Vec; -} - /// An endpoint of a range of keys. #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub enum Bound { diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 5ca3cb380583b..0799e14e6574d 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -938,572 +938,3 @@ impl Hash for LinkedList { } } } - -#[cfg(test)] -mod tests { - use prelude::*; - use std::rand; - use std::hash::{self, SipHasher}; - use std::thread; - use test::Bencher; - use test; - - use super::{LinkedList, Node}; - - pub fn check_links(list: &LinkedList) { - let mut len = 0; - let mut last_ptr: Option<&Node> = None; - let mut node_ptr: &Node; - match list.list_head { - None => { assert_eq!(0, list.length); return } - Some(ref node) => node_ptr = &**node, - } - loop { - match (last_ptr, node_ptr.prev.resolve_immut()) { - (None , None ) => {} - (None , _ ) => panic!("prev link for list_head"), - (Some(p), Some(pptr)) => { - assert_eq!(p as *const Node, pptr as *const Node); - } - _ => panic!("prev link is none, not good"), - } - match node_ptr.next { - Some(ref next) => { - last_ptr = Some(node_ptr); - node_ptr = &**next; - len += 1; - } - None => { - len += 1; - break; - } - } - } - assert_eq!(len, list.length); - } - - #[test] - fn test_basic() { - let mut m = LinkedList::>::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 { - list_from(&[0,1,2,3,4,5,6]) - } - - #[cfg(test)] - fn list_from(v: &[T]) -> LinkedList { - v.iter().cloned().collect() - } - - #[test] - fn test_append() { - // Empty to empty - { - let mut m = LinkedList::::new(); - let mut n = LinkedList::new(); - m.append(&mut n); - check_links(&m); - assert_eq!(m.len(), 0); - assert_eq!(n.len(), 0); - } - // Non-empty to empty - { - let mut m = LinkedList::new(); - let mut n = LinkedList::new(); - n.push_back(2); - m.append(&mut n); - check_links(&m); - assert_eq!(m.len(), 1); - assert_eq!(m.pop_back(), Some(2)); - assert_eq!(n.len(), 0); - check_links(&m); - } - // Empty to non-empty - { - let mut m = LinkedList::new(); - let mut n = LinkedList::new(); - m.push_back(2); - m.append(&mut n); - check_links(&m); - assert_eq!(m.len(), 1); - assert_eq!(m.pop_back(), Some(2)); - check_links(&m); - } - - // Non-empty to non-empty - let v = vec![1,2,3,4,5]; - let u = vec![9,8,1,2,3,4,5]; - let mut m = list_from(&v); - let mut n = list_from(&u); - m.append(&mut n); - check_links(&m); - let mut sum = v; - sum.push_all(&u); - assert_eq!(sum.len(), m.len()); - for elt in sum { - assert_eq!(m.pop_front(), Some(elt)) - } - assert_eq!(n.len(), 0); - // let's make sure it's working properly, since we - // did some direct changes to private members - n.push_back(3); - assert_eq!(n.len(), 1); - assert_eq!(n.pop_front(), Some(3)); - check_links(&n); - } - - #[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_insert_prev() { - let mut m = list_from(&[0,2,4,6,8]); - let len = m.len(); - { - let mut it = m.iter_mut(); - it.insert_next(-2); - loop { - match it.next() { - None => break, - Some(elt) => { - it.insert_next(*elt + 1); - match it.peek_next() { - Some(x) => assert_eq!(*x, *elt + 2), - None => assert_eq!(8, *elt), - } - } - } - } - it.insert_next(0); - it.insert_next(1); - } - check_links(&m); - assert_eq!(m.len(), 3 + len * 2); - assert_eq!(m.into_iter().collect::>(), [-2,0,1,2,3,4,5,6,7,8,9,0,1]); - } - - #[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_send() { - let n = list_from(&[1,2,3]); - thread::spawn(move || { - check_links(&n); - let a: &[_] = &[&1,&2,&3]; - assert_eq!(a, n.iter().collect::>()); - }).join().ok().unwrap(); - } - - #[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::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&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::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&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_fuzz() { - for _ in 0..25 { - fuzz_test(3); - fuzz_test(16); - fuzz_test(189); - } - } - - #[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\"]"); - } - - #[cfg(test)] - fn fuzz_test(sz: i32) { - let mut m: LinkedList<_> = LinkedList::new(); - let mut v = vec![]; - for i in 0..sz { - check_links(&m); - let r: u8 = rand::random(); - match r % 6 { - 0 => { - m.pop_back(); - v.pop(); - } - 1 => { - if !v.is_empty() { - m.pop_front(); - v.remove(0); - } - } - 2 | 4 => { - m.push_front(-i); - v.insert(0, -i); - } - 3 | 5 | _ => { - m.push_back(i); - v.push(i); - } - } - } - - check_links(&m); - - let mut i = 0; - for (a, &b) in m.into_iter().zip(v.iter()) { - i += 1; - assert_eq!(a, b); - } - assert_eq!(i, v.len()); - } - - #[bench] - fn bench_collect_into(b: &mut test::Bencher) { - let v = &[0; 64]; - b.iter(|| { - let _: LinkedList<_> = v.iter().cloned().collect(); - }) - } - - #[bench] - fn bench_push_front(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_front(0); - }) - } - - #[bench] - fn bench_push_back(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_back(0); - }) - } - - #[bench] - fn bench_push_back_pop_back(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_back(0); - m.pop_back(); - }) - } - - #[bench] - fn bench_push_front_pop_front(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_front(0); - m.pop_front(); - }) - } - - #[bench] - fn bench_iter(b: &mut test::Bencher) { - let v = &[0; 128]; - let m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter().count() == 128); - }) - } - #[bench] - fn bench_iter_mut(b: &mut test::Bencher) { - let v = &[0; 128]; - let mut m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter_mut().count() == 128); - }) - } - #[bench] - fn bench_iter_rev(b: &mut test::Bencher) { - let v = &[0; 128]; - let m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter().rev().count() == 128); - }) - } - #[bench] - fn bench_iter_mut_rev(b: &mut test::Bencher) { - let v = &[0; 128]; - let mut m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter_mut().rev().count() == 128); - }) - } -} diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 0fe513d3118c5..15b67376887c2 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -2339,1633 +2339,3 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order old } } - -#[cfg(test)] -mod tests { - use alloc::boxed::Box; - use core::cmp::Ordering::{Greater, Less, Equal}; - use core::prelude::{Some, None, Clone}; - use core::prelude::{Iterator, IteratorExt}; - use core::prelude::{AsSlice}; - use core::prelude::Ord; - use core::default::Default; - use core::mem; - use std::iter::RandomAccessIterator; - use std::rand::{Rng, thread_rng}; - use std::rc::Rc; - use string::ToString; - use vec::Vec; - use super::{ElementSwaps, SliceConcatExt, SliceExt}; - - 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.as_slice(); - 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::(), 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_tail() { - let mut a = vec![11]; - let b: &[i32] = &[]; - assert_eq!(a.tail(), b); - a = vec![11, 12]; - let b: &[i32] = &[12]; - assert_eq!(a.tail(), b); - } - - #[test] - fn test_tail_mut() { - let mut a = vec![11]; - let b: &mut [i32] = &mut []; - assert!(a.tail_mut() == b); - a = vec![11, 12]; - let b: &mut [_] = &mut [12]; - assert!(a.tail_mut() == b); - } - - #[test] - #[should_panic] - fn test_tail_empty() { - let a = Vec::::new(); - a.tail(); - } - - #[test] - #[should_panic] - fn test_tail_mut_empty() { - let mut a = Vec::::new(); - a.tail_mut(); - } - - #[test] - fn test_init() { - let mut a = vec![11]; - let b: &[i32] = &[]; - assert_eq!(a.init(), b); - a = vec![11, 12]; - let b: &[_] = &[11]; - assert_eq!(a.init(), b); - } - - #[test] - fn test_init_mut() { - let mut a = vec![11]; - let b: &mut [i32] = &mut []; - assert!(a.init_mut() == b); - a = vec![11, 12]; - let b: &mut [_] = &mut [11]; - assert!(a.init_mut() == b); - } - - #[test] - #[should_panic] - fn test_init_empty() { - let a = Vec::::new(); - a.init(); - } - - #[test] - #[should_panic] - fn test_init_mut_empty() { - let mut a = Vec::::new(); - a.init_mut(); - } - - #[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> = Vec::new(); - v.push(box 0u8); - v.push(box 0u8); - v.push(box 0u8); - 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> = 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> = 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_dedup() { - fn case(a: Vec, b: Vec) { - 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_unique() { - let mut v0: Vec> = vec![box 1, box 1, box 2, box 3]; - v0.dedup(); - let mut v1: Vec> = vec![box 1, box 2, box 2, box 3]; - v1.dedup(); - let mut v2: Vec> = 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 test_dedup_shared() { - let mut v0: Vec> = vec![box 1, box 1, box 2, box 3]; - v0.dedup(); - let mut v1: Vec> = vec![box 1, box 2, box 2, box 3]; - v1.dedup(); - let mut v2: Vec> = vec![box 1, box 2, box 3, box 3]; - v2.dedup(); - /* - * If the pointers were leaked or otherwise misused, valgrind and/or - * rt should raise errors. - */ - } - - #[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_element_swaps() { - let mut v = [1, 2, 3]; - for (i, (a, b)) in ElementSwaps::new(v.len()).enumerate() { - v.swap(a, b); - match i { - 0 => assert!(v == [1, 3, 2]), - 1 => assert!(v == [3, 1, 2]), - 2 => assert!(v == [3, 2, 1]), - 3 => assert!(v == [2, 3, 1]), - 4 => assert!(v == [2, 1, 3]), - 5 => assert!(v == [1, 2, 3]), - _ => panic!(), - } - } - } - - #[test] - fn test_permutations() { - { - let v: [i32; 0] = []; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 1); - assert_eq!(max_opt.unwrap(), 1); - assert_eq!(it.next(), Some(v.to_vec())); - assert_eq!(it.next(), None); - } - { - let v = ["Hello".to_string()]; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 1); - assert_eq!(max_opt.unwrap(), 1); - assert_eq!(it.next(), Some(v.to_vec())); - assert_eq!(it.next(), None); - } - { - let v = [1, 2, 3]; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 3*2); - assert_eq!(max_opt.unwrap(), 3*2); - assert_eq!(it.next(), Some(vec![1,2,3])); - assert_eq!(it.next(), Some(vec![1,3,2])); - assert_eq!(it.next(), Some(vec![3,1,2])); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 3); - assert_eq!(max_opt.unwrap(), 3); - assert_eq!(it.next(), Some(vec![3,2,1])); - assert_eq!(it.next(), Some(vec![2,3,1])); - assert_eq!(it.next(), Some(vec![2,1,3])); - assert_eq!(it.next(), None); - } - { - // check that we have N! permutations - let v = ['A', 'B', 'C', 'D', 'E', 'F']; - let mut amt = 0; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - for _perm in it.by_ref() { - amt += 1; - } - assert_eq!(amt, it.swaps.swaps_made); - assert_eq!(amt, min_size); - assert_eq!(amt, 2 * 3 * 4 * 5 * 6); - assert_eq!(amt, max_opt.unwrap()); - } - } - - #[test] - fn test_lexicographic_permutations() { - let v : &mut[_] = &mut[1, 2, 3, 4, 5]; - assert!(v.prev_permutation() == false); - assert!(v.next_permutation()); - let b: &mut[_] = &mut[1, 2, 3, 5, 4]; - assert!(v == b); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[1, 2, 3, 4, 5]; - assert!(v == b); - assert!(v.next_permutation()); - assert!(v.next_permutation()); - let b: &mut[_] = &mut[1, 2, 4, 3, 5]; - assert!(v == b); - assert!(v.next_permutation()); - let b: &mut[_] = &mut[1, 2, 4, 5, 3]; - assert!(v == b); - - let v : &mut[_] = &mut[1, 0, 0, 0]; - assert!(v.next_permutation() == false); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[0, 1, 0, 0]; - assert!(v == b); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[0, 0, 1, 0]; - assert!(v == b); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[0, 0, 0, 1]; - assert!(v == b); - assert!(v.prev_permutation() == false); - } - - #[test] - fn test_lexicographic_permutations_empty_and_short() { - let empty : &mut[i32] = &mut[]; - assert!(empty.next_permutation() == false); - let b: &mut[i32] = &mut[]; - assert!(empty == b); - assert!(empty.prev_permutation() == false); - assert!(empty == b); - - let one_elem : &mut[_] = &mut[4]; - assert!(one_elem.prev_permutation() == false); - let b: &mut[_] = &mut[4]; - assert!(one_elem == b); - assert!(one_elem.next_permutation() == false); - assert!(one_elem == b); - - let two_elem : &mut[_] = &mut[1, 2]; - assert!(two_elem.prev_permutation() == false); - let b : &mut[_] = &mut[1, 2]; - let c : &mut[_] = &mut[2, 1]; - assert!(two_elem == b); - assert!(two_elem.next_permutation()); - assert!(two_elem == c); - assert!(two_elem.next_permutation() == false); - assert!(two_elem == c); - assert!(two_elem.prev_permutation()); - assert!(two_elem == b); - assert!(two_elem.prev_permutation() == false); - assert!(two_elem == b); - } - - #[test] - fn test_position_elem() { - assert!([].position_elem(&1).is_none()); - - let v1 = vec![1, 2, 3, 3, 2, 5]; - assert_eq!(v1.position_elem(&1), Some(0)); - assert_eq!(v1.position_elem(&2), Some(1)); - assert_eq!(v1.position_elem(&5), Some(5)); - assert!(v1.position_elem(&4).is_none()); - } - - #[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::::new(); - v3.reverse(); - assert!(v3.is_empty()); - } - - #[test] - fn test_sort() { - for len in 4..25 { - for _ in 0..100 { - let mut v: Vec<_> = thread_rng().gen_iter::().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])); - } - } - - // shouldn't panic - let mut v: [i32; 0] = []; - v.sort(); - - let mut v = [0xDEADBEEFu64]; - v.sort(); - assert!(v == [0xDEADBEEF]); - } - - #[test] - fn test_sort_stability() { - for len in 4..25 { - 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::() % 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; 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.connect(&0), [1, 0, 2, 3]); - let v: &[&[_]] = &[&[1], &[2], &[3]]; - assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]); - } - - #[test] - fn test_connect() { - let v: [Vec; 0] = []; - assert_eq!(v.connect(&0), []); - assert_eq!([vec![1], vec![2, 3]].connect(&0), [1, 0, 2, 3]); - assert_eq!([vec![1], vec![2], vec![3]].connect(&0), [1, 0, 2, 0, 3]); - - let v: [&[_]; 2] = [&[1], &[2, 3]]; - assert_eq!(v.connect(&0), [1, 0, 2, 3]); - let v: [&[_]; 3] = [&[1], &[2], &[3]]; - assert_eq!(v.connect(&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.slice(1, 3); - assert_eq!(v.len(), 2); - assert_eq!(v[0], 2); - assert_eq!(v[1], 3); - } - - #[test] - #[should_panic] - fn test_permute_fail() { - let v: [(Box<_>, Rc<_>); 4] = - [(box 0, Rc::new(0)), (box 0, Rc::new(0)), - (box 0, Rc::new(0)), (box 0, Rc::new(0))]; - let mut i = 0; - for _ in v.permutations() { - if i == 2 { - panic!() - } - i += 1; - } - } - - #[test] - fn test_total_ord() { - let c = &[1, 2, 3]; - [1, 2, 3, 4][..].cmp(c) == Greater; - let c = &[1, 2, 3, 4]; - [1, 2, 3][..].cmp(c) == Less; - let c = &[1, 2, 3, 6]; - [1, 2, 3, 4][..].cmp(c) == Equal; - let c = &[1, 2, 3, 4, 5, 6]; - [1, 2, 3, 4, 5, 5, 5, 5][..].cmp(c) == Less; - let c = &[1, 2, 3, 4]; - [2, 2][..].cmp(c) == Greater; - } - - #[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_random_access_iterator() { - let xs = [1, 2, 5, 10, 11]; - let mut it = xs.iter(); - - assert_eq!(it.indexable(), 5); - assert_eq!(it.idx(0).unwrap(), &1); - assert_eq!(it.idx(2).unwrap(), &5); - assert_eq!(it.idx(4).unwrap(), &11); - assert!(it.idx(5).is_none()); - - assert_eq!(it.next().unwrap(), &1); - assert_eq!(it.indexable(), 4); - assert_eq!(it.idx(0).unwrap(), &2); - assert_eq!(it.idx(3).unwrap(), &11); - assert!(it.idx(4).is_none()); - - assert_eq!(it.next().unwrap(), &2); - assert_eq!(it.indexable(), 3); - assert_eq!(it.idx(1).unwrap(), &10); - assert!(it.idx(3).is_none()); - - assert_eq!(it.next().unwrap(), &5); - assert_eq!(it.indexable(), 2); - assert_eq!(it.idx(1).unwrap(), &11); - - assert_eq!(it.next().unwrap(), &10); - assert_eq!(it.indexable(), 1); - assert_eq!(it.idx(0).unwrap(), &11); - assert!(it.idx(1).is_none()); - - assert_eq!(it.next().unwrap(), &11); - assert_eq!(it.indexable(), 0); - assert!(it.idx(0).is_none()); - - 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_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_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::>(), - splits); - let splits: &[&[_]] = &[&[], &[2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 1).collect::>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4], &[]]; - assert_eq!(xs.split(|x| *x == 5).collect::>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 10).collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[], &[], &[], &[], &[]]; - assert_eq!(xs.split(|_| true).collect::>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split(|x| *x == 5).collect::>(), splits); - } - - #[test] - fn test_splitnator() { - let xs = &[1,2,3,4,5]; - - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.splitn(0, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[1], &[3,4,5]]; - assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[], &[], &[4,5]]; - assert_eq!(xs.splitn(3, |_| true).collect::>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.splitn(1, |x| *x == 5).collect::>(), 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(0, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&mut[_]] = &[&mut [1], &mut [3,4,5]]; - assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&mut[_]] = &[&mut [], &mut [], &mut [], &mut [4,5]]; - assert_eq!(xs.splitn_mut(3, |_| true).collect::>(), - splits); - - let xs: &mut [i32] = &mut []; - let splits: &[&mut[i32]] = &[&mut []]; - assert_eq!(xs.splitn_mut(1, |x| *x == 5).collect::>(), - 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::>(), - splits); - let splits: &[&[_]] = &[&[2,3,4,5], &[]]; - assert_eq!(xs.split(|x| *x == 1).rev().collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[1,2,3,4]]; - assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 10).rev().collect::>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), splits); - } - - #[test] - fn test_rsplitnator() { - let xs = &[1,2,3,4,5]; - - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.rsplitn(0, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[5], &[1,2,3]]; - assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[], &[], &[1,2]]; - assert_eq!(xs.rsplitn(3, |_| true).collect::>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.rsplitn(1, |x| *x == 5).collect::>(), splits); - } - - #[test] - fn test_windowsator() { - let v = &[1,2,3,4]; - - let wins: &[&[_]] = &[&[1,2], &[2,3], &[3,4]]; - assert_eq!(v.windows(2).collect::>(), wins); - - let wins: &[&[_]] = &[&[1,2,3], &[2,3,4]]; - assert_eq!(v.windows(3).collect::>(), wins); - assert!(v.windows(6).next().is_none()); - - let wins: &[&[_]] = &[&[3,4], &[2,3], &[1,2]]; - assert_eq!(v.windows(2).rev().collect::>(), wins); - let mut it = v.windows(2); - assert_eq!(it.indexable(), 3); - let win: &[_] = &[1,2]; - assert_eq!(it.idx(0).unwrap(), win); - let win: &[_] = &[2,3]; - assert_eq!(it.idx(1).unwrap(), win); - let win: &[_] = &[3,4]; - assert_eq!(it.idx(2).unwrap(), win); - assert_eq!(it.idx(3), None); - } - - #[test] - #[should_panic] - fn test_windowsator_0() { - let v = &[1,2,3,4]; - let _it = v.windows(0); - } - - #[test] - fn test_chunksator() { - use core::iter::ExactSizeIterator; - - 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::>(), chunks); - let chunks: &[&[_]] = &[&[1,2,3], &[4,5]]; - assert_eq!(v.chunks(3).collect::>(), chunks); - let chunks: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(v.chunks(6).collect::>(), chunks); - - let chunks: &[&[_]] = &[&[5], &[3,4], &[1,2]]; - assert_eq!(v.chunks(2).rev().collect::>(), chunks); - let mut it = v.chunks(2); - assert_eq!(it.indexable(), 3); - - let chunk: &[_] = &[1,2]; - assert_eq!(it.idx(0).unwrap(), chunk); - let chunk: &[_] = &[3,4]; - assert_eq!(it.idx(1).unwrap(), chunk); - let chunk: &[_] = &[5]; - assert_eq!(it.idx(2).unwrap(), chunk); - assert_eq!(it.idx(3), None); - } - - #[test] - #[should_panic] - fn test_chunksator_0() { - let v = &[1,2,3,4]; - let _it = v.chunks(0); - } - - #[test] - fn test_move_from() { - let mut a = [1,2,3,4,5]; - let b = vec![6,7,8]; - assert_eq!(a.move_from(b, 0, 3), 3); - assert!(a == [6,7,8,4,5]); - let mut a = [7,2,8,1]; - let b = vec![3,1,4,1,5,9]; - assert_eq!(a.move_from(b, 0, 6), 4); - assert!(a == [3,1,4,1]); - let mut a = [1,2,3,4]; - let b = vec![5,6,7,8,9,0]; - assert_eq!(a.move_from(b, 2, 3), 1); - assert!(a == [7,2,3,4]); - let mut a = [1,2,3,4,5]; - let b = vec![5,6,7,8,9,0]; - assert_eq!(a[2..4].move_from(b,1,6), 2); - assert!(a == [1,2,6,7,5]); - } - - #[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::::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); - } - - #[test] - fn test_bytes_set_memory() { - use slice::bytes::MutableByteVector; - let mut values = [1,2,3,4,5]; - values[0..5].set_memory(0xAB); - assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]); - values[2..4].set_memory(0xFF); - assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]); - } - - #[test] - #[should_panic] - fn test_overflow_does_not_cause_segfault() { - let mut v = vec![]; - v.reserve_exact(-1); - 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(-1); - v.push(Rc::new(2)); - } - - #[test] - fn test_mut_split_at() { - let mut values = [1u8,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::>()); - } - - #[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() { - use core::iter::ExactSizeIterator; - - 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]); - } -} - -#[cfg(test)] -mod bench { - use prelude::*; - use core::mem; - use core::ptr; - use core::iter::repeat; - use std::rand::{weak_rng, Rng}; - use test::{Bencher, black_box}; - - #[bench] - fn iterator(b: &mut Bencher) { - // peculiar numbers to stop LLVM from optimising the summation - // out. - let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect(); - - b.iter(|| { - let mut sum = 0; - for x in &v { - sum += *x; - } - // sum == 11806, to stop dead code elimination. - if sum == 0 {panic!()} - }) - } - - #[bench] - fn mut_iterator(b: &mut Bencher) { - let mut v: Vec<_> = repeat(0).take(100).collect(); - - b.iter(|| { - let mut i = 0; - for x in &mut v { - *x = i; - i += 1; - } - }) - } - - #[bench] - fn concat(b: &mut Bencher) { - let xss: Vec> = - (0..100).map(|i| (0..i).collect()).collect(); - b.iter(|| { - xss.concat(); - }); - } - - #[bench] - fn connect(b: &mut Bencher) { - let xss: Vec> = - (0..100).map(|i| (0..i).collect()).collect(); - b.iter(|| { - xss.connect(&0) - }); - } - - #[bench] - fn push(b: &mut Bencher) { - let mut vec = Vec::::new(); - b.iter(|| { - vec.push(0); - black_box(&vec); - }); - } - - #[bench] - fn starts_with_same_vector(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.starts_with(&vec) - }) - } - - #[bench] - fn starts_with_single_element(b: &mut Bencher) { - let vec: Vec<_> = vec![0]; - b.iter(|| { - vec.starts_with(&vec) - }) - } - - #[bench] - fn starts_with_diff_one_element_at_end(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - let mut match_vec: Vec<_> = (0..99).collect(); - match_vec.push(0); - b.iter(|| { - vec.starts_with(&match_vec) - }) - } - - #[bench] - fn ends_with_same_vector(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.ends_with(&vec) - }) - } - - #[bench] - fn ends_with_single_element(b: &mut Bencher) { - let vec: Vec<_> = vec![0]; - b.iter(|| { - vec.ends_with(&vec) - }) - } - - #[bench] - fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - let mut match_vec: Vec<_> = (0..100).collect(); - match_vec[0] = 200; - b.iter(|| { - vec.starts_with(&match_vec) - }) - } - - #[bench] - fn contains_last_element(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.contains(&99) - }) - } - - #[bench] - fn zero_1kb_from_elem(b: &mut Bencher) { - b.iter(|| { - repeat(0u8).take(1024).collect::>() - }); - } - - #[bench] - fn zero_1kb_set_memory(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::::with_capacity(1024); - unsafe { - let vp = v.as_mut_ptr(); - ptr::set_memory(vp, 0, 1024); - v.set_len(1024); - } - v - }); - } - - #[bench] - fn zero_1kb_loop_set(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::::with_capacity(1024); - unsafe { - v.set_len(1024); - } - for i in 0..1024 { - v[i] = 0; - } - }); - } - - #[bench] - fn zero_1kb_mut_iter(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::::with_capacity(1024); - unsafe { - v.set_len(1024); - } - for x in &mut v { - *x = 0; - } - v - }); - } - - #[bench] - fn random_inserts(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = repeat((0, 0)).take(30).collect(); - for _ in 0..100 { - let l = v.len(); - v.insert(rng.gen::() % (l + 1), - (1, 1)); - } - }) - } - #[bench] - fn random_removes(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = repeat((0, 0)).take(130).collect(); - for _ in 0..100 { - let l = v.len(); - v.remove(rng.gen::() % l); - } - }) - } - - #[bench] - fn sort_random_small(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = rng.gen_iter::().take(5).collect(); - v.sort(); - }); - b.bytes = 5 * mem::size_of::() as u64; - } - - #[bench] - fn sort_random_medium(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = rng.gen_iter::().take(100).collect(); - v.sort(); - }); - b.bytes = 100 * mem::size_of::() as u64; - } - - #[bench] - fn sort_random_large(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = rng.gen_iter::().take(10000).collect(); - v.sort(); - }); - b.bytes = 10000 * mem::size_of::() as u64; - } - - #[bench] - fn sort_sorted(b: &mut Bencher) { - let mut v: Vec<_> = (0..10000).collect(); - b.iter(|| { - v.sort(); - }); - b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; - } - - type BigSortable = (u64, u64, u64, u64); - - #[bench] - fn sort_big_random_small(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v = rng.gen_iter::().take(5) - .collect::>(); - v.sort(); - }); - b.bytes = 5 * mem::size_of::() as u64; - } - - #[bench] - fn sort_big_random_medium(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v = rng.gen_iter::().take(100) - .collect::>(); - v.sort(); - }); - b.bytes = 100 * mem::size_of::() as u64; - } - - #[bench] - fn sort_big_random_large(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v = rng.gen_iter::().take(10000) - .collect::>(); - v.sort(); - }); - b.bytes = 10000 * mem::size_of::() as u64; - } - - #[bench] - fn sort_big_sorted(b: &mut Bencher) { - let mut v: Vec = (0..10000).map(|i| (i, i, i, i)).collect(); - b.iter(|| { - v.sort(); - }); - b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; - } -} diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 06674f6f0ab75..fc93b0b75a7ab 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -2690,1668 +2690,3 @@ impl str { return s; } } - -#[cfg(test)] -mod tests { - use prelude::*; - - use core::iter::AdditiveIterator; - use super::from_utf8; - use super::Utf8Error; - - #[test] - fn test_le() { - assert!("" <= ""); - assert!("" <= "foo"); - assert!("foo" <= "foo"); - assert!("foo" != "bar"); - } - - #[test] - fn test_len() { - assert_eq!("".len(), 0); - assert_eq!("hello world".len(), 11); - assert_eq!("\x63".len(), 1); - assert_eq!("\u{a2}".len(), 2); - assert_eq!("\u{3c0}".len(), 2); - assert_eq!("\u{2620}".len(), 3); - assert_eq!("\u{1d11e}".len(), 4); - - assert_eq!("".chars().count(), 0); - assert_eq!("hello world".chars().count(), 11); - assert_eq!("\x63".chars().count(), 1); - assert_eq!("\u{a2}".chars().count(), 1); - assert_eq!("\u{3c0}".chars().count(), 1); - assert_eq!("\u{2620}".chars().count(), 1); - assert_eq!("\u{1d11e}".chars().count(), 1); - assert_eq!("ประเทศไทย中华Việt Nam".chars().count(), 19); - - assert_eq!("hello".width(false), 10); - assert_eq!("hello".width(true), 10); - assert_eq!("\0\0\0\0\0".width(false), 0); - assert_eq!("\0\0\0\0\0".width(true), 0); - assert_eq!("".width(false), 0); - assert_eq!("".width(true), 0); - assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(false), 4); - assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(true), 8); - } - - #[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 = String::from_str(""); - let s: String = empty.chars().collect(); - assert_eq!(empty, s); - let data = String::from_str("ประเทศไทย中"); - let s: String = data.chars().collect(); - assert_eq!(data, s); - } - - #[test] - fn test_into_bytes() { - let data = String::from_str("asdf"); - let buf = data.into_bytes(); - assert_eq!(b"asdf", buf); - } - - #[test] - fn test_find_str() { - // byte positions - assert_eq!("".find_str(""), Some(0)); - assert!("banana".find_str("apple pie").is_none()); - - let data = "abcabc"; - assert_eq!(data[0..6].find_str("ab"), Some(0)); - assert_eq!(data[2..6].find_str("ab"), Some(3 - 2)); - assert!(data[2..4].find_str("ab").is_none()); - - let string = "ประเทศไทย中华Việt Nam"; - let mut data = String::from_str(string); - data.push_str(string); - assert!(data.find_str("ไท华").is_none()); - assert_eq!(data[0..43].find_str(""), Some(0)); - assert_eq!(data[6..43].find_str(""), Some(6 - 6)); - - assert_eq!(data[0..43].find_str("ประ"), Some( 0)); - assert_eq!(data[0..43].find_str("ทศไ"), Some(12)); - assert_eq!(data[0..43].find_str("ย中"), Some(24)); - assert_eq!(data[0..43].find_str("iệt"), Some(34)); - assert_eq!(data[0..43].find_str("Nam"), Some(40)); - - assert_eq!(data[43..86].find_str("ประ"), Some(43 - 43)); - assert_eq!(data[43..86].find_str("ทศไ"), Some(55 - 43)); - assert_eq!(data[43..86].find_str("ย中"), Some(67 - 43)); - assert_eq!(data[43..86].find_str("iệt"), Some(77 - 43)); - assert_eq!(data[43..86].find_str("Nam"), Some(83 - 43)); - } - - #[test] - fn test_slice_chars() { - fn t(a: &str, b: &str, start: usize) { - assert_eq!(a.slice_chars(start, start + b.chars().count()), b); - } - t("", "", 0); - t("hello", "llo", 2); - t("hello", "el", 1); - t("αβλ", "β", 1); - t("αβλ", "", 3); - assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".slice_chars(2, 8)); - } - - 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_concat!("ab", vec!["a", "b"]); - test_concat!("ab", vec![s("a"), s("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_connect { - ($expected: expr, $string: expr, $delim: expr) => { - { - let s = $string.connect($delim); - assert_eq!($expected, s); - } - } - } - - #[test] - fn test_connect_for_different_types() { - test_connect!("a-b", ["a", "b"], "-"); - let hyphen = "-".to_string(); - test_connect!("a-b", [s("a"), s("b")], &*hyphen); - test_connect!("a-b", vec!["a", "b"], &*hyphen); - test_connect!("a-b", &*vec!["a", "b"], "-"); - test_connect!("a-b", vec![s("a"), s("b")], "-"); - } - - #[test] - fn test_connect_for_different_lengths() { - let empty: &[&str] = &[]; - test_connect!("", empty, "-"); - test_connect!("a", ["a"], "-"); - test_connect!("a-b", ["a", "b"], "-"); - test_connect!("-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!(half_a_million_letter_a() == - unsafe {String::from_str(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_replace() { - let a = "a"; - assert_eq!("".replace(a, "b"), String::from_str("")); - assert_eq!("a".replace(a, "b"), String::from_str("b")); - assert_eq!("ab".replace(a, "b"), String::from_str("bb")); - let test = "test"; - assert!(" test test ".replace(test, "toast") == - String::from_str(" toast toast ")); - assert_eq!(" test test ".replace(test, ""), String::from_str(" ")); - } - - #[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_slice() { - assert_eq!("ab", "abc".slice(0, 2)); - assert_eq!("bc", "abc".slice(1, 3)); - assert_eq!("", "abc".slice(1, 1)); - assert_eq!("\u{65e5}", "\u{65e5}\u{672c}".slice(0, 3)); - - let data = "ประเทศไทย中华"; - assert_eq!("ป", data.slice(0, 3)); - assert_eq!("ร", data.slice(3, 6)); - assert_eq!("", data.slice(3, 3)); - assert_eq!("华", data.slice(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!(half_a_million_letter_x() == - String::from_str(letters.slice(0, 3 * 500000))); - } - - #[test] - fn test_slice_2() { - let ss = "中华Việt Nam"; - - assert_eq!("华", ss.slice(3, 6)); - assert_eq!("Việt Nam", ss.slice(6, 16)); - - assert_eq!("ab", "abc".slice(0, 2)); - assert_eq!("bc", "abc".slice(1, 3)); - assert_eq!("", "abc".slice(1, 1)); - - assert_eq!("中", ss.slice(0, 3)); - assert_eq!("华V", ss.slice(3, 7)); - assert_eq!("", ss.slice(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".slice(0, 2); - } - - #[test] - fn test_slice_from() { - assert_eq!("abcd".slice_from(0), "abcd"); - assert_eq!("abcd".slice_from(2), "cd"); - assert_eq!("abcd".slice_from(4), ""); - } - #[test] - fn test_slice_to() { - assert_eq!("abcd".slice_to(0), ""); - assert_eq!("abcd".slice_to(2), "ab"); - assert_eq!("abcd".slice_to(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_slice_shift_char() { - let data = "ประเทศไทย中"; - assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中"))); - } - - #[test] - fn test_slice_shift_char_2() { - let empty = ""; - assert_eq!(empty.slice_shift_char(), None); - } - - #[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 test_is_utf16() { - use unicode::str::is_utf16; - macro_rules! pos { - ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } } - } - - // non-surrogates - pos!(&[0x0000], - &[0x0001, 0x0002], - &[0xD7FF], - &[0xE000]); - - // surrogate pairs (randomly generated with Python 3's - // .encode('utf-16be')) - pos!(&[0xdb54, 0xdf16, 0xd880, 0xdee0, 0xdb6a, 0xdd45], - &[0xd91f, 0xdeb1, 0xdb31, 0xdd84, 0xd8e2, 0xde14], - &[0xdb9f, 0xdc26, 0xdb6f, 0xde58, 0xd850, 0xdfae]); - - // mixtures (also random) - pos!(&[0xd921, 0xdcc2, 0x002d, 0x004d, 0xdb32, 0xdf65], - &[0xdb45, 0xdd2d, 0x006a, 0xdacd, 0xddfe, 0x0006], - &[0x0067, 0xd8ff, 0xddb7, 0x000f, 0xd900, 0xdc80]); - - // negative tests - macro_rules! neg { - ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } } - } - - neg!( - // surrogate + regular unit - &[0xdb45, 0x0000], - // surrogate + lead surrogate - &[0xd900, 0xd900], - // unterminated surrogate - &[0xd8ff], - // trail surrogate without a lead - &[0xddb7]); - - // random byte sequences that Python 3's .decode('utf-16be') - // failed on - neg!(&[0x5b3d, 0x0141, 0xde9e, 0x8fdc, 0xc6e7], - &[0xdf5a, 0x82a5, 0x62b9, 0xb447, 0x92f3], - &[0xda4e, 0x42bc, 0x4462, 0xee98, 0xc2ca], - &[0xbe00, 0xb04a, 0x6ecb, 0xdd89, 0xe278], - &[0x0465, 0xab56, 0xdbb6, 0xa893, 0x665e], - &[0x6b7f, 0x0a19, 0x40f4, 0xa657, 0xdcc5], - &[0x9b50, 0xda5e, 0x24ec, 0x03ad, 0x6dee], - &[0x8d17, 0xcaa7, 0xf4ae, 0xdf6e, 0xbed7], - &[0xdaee, 0x2584, 0x7d30, 0xa626, 0x121a], - &[0xd956, 0x4b43, 0x7570, 0xccd6, 0x4f4a], - &[0x9dcf, 0x1b49, 0x4ba5, 0xfce9, 0xdffe], - &[0x6572, 0xce53, 0xb05a, 0xf6af, 0xdacf], - &[0x1b90, 0x728c, 0x9906, 0xdb68, 0xf46e], - &[0x1606, 0xbeca, 0xbe76, 0x860f, 0xdfa5], - &[0x8b4f, 0xde7a, 0xd220, 0x9fac, 0x2b6f], - &[0xb8fe, 0xebbe, 0xda32, 0x1a5f, 0x8b8b], - &[0x934b, 0x8956, 0xc434, 0x1881, 0xddf7], - &[0x5a95, 0x13fc, 0xf116, 0xd89b, 0x93f9], - &[0xd640, 0x71f1, 0xdd7d, 0x77eb, 0x1cd8], - &[0x348b, 0xaef0, 0xdb2c, 0xebf1, 0x1282], - &[0x50d7, 0xd824, 0x5010, 0xb369, 0x22ea]); - } - - #[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_str(""); - 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 test_subslice_offset() { - let a = "kernelsprite"; - let b = &a[7..a.len()]; - let c = &a[0..a.len() - 6]; - assert_eq!(a.subslice_offset(b), 7); - assert_eq!(a.subslice_offset(c), 0); - - let string = "a\nb\nc"; - let lines: Vec<&str> = string.lines().collect(); - assert_eq!(string.subslice_offset(lines[0]), 0); - assert_eq!(string.subslice_offset(lines[1]), 2); - assert_eq!(string.subslice_offset(lines[2]), 4); - } - - #[test] - #[should_panic] - fn test_subslice_offset_2() { - let a = "alchemiter"; - let b = "cruxtruder"; - a.subslice_offset(b); - } - - #[test] - fn vec_str_conversions() { - let s1: String = String::from_str("All mimsy were the borogoves"); - - let v: Vec = s1.as_bytes().to_vec(); - let s2: String = String::from_str(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]; - debug!("{}", a); - debug!("{}", b); - 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_char('b')); - assert!("a".contains_char('a')); - assert!(!"abc".contains_char('d')); - assert!(!"".contains_char('a')); - } - - #[test] - fn test_char_at() { - let s = "ศไทย中华Việt Nam"; - let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - let mut pos = 0; - for ch in &v { - assert!(s.char_at(pos) == *ch); - pos += ch.to_string().len(); - } - } - - #[test] - fn test_char_at_reverse() { - let s = "ศไทย中华Việt Nam"; - let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - let mut pos = s.len(); - for ch in v.iter().rev() { - assert!(s.char_at_reverse(pos) == *ch); - pos -= ch.to_string().len(); - } - } - - #[test] - fn test_escape_unicode() { - assert_eq!("abc".escape_unicode(), - String::from_str("\\u{61}\\u{62}\\u{63}")); - assert_eq!("a c".escape_unicode(), - String::from_str("\\u{61}\\u{20}\\u{63}")); - assert_eq!("\r\n\t".escape_unicode(), - String::from_str("\\u{d}\\u{a}\\u{9}")); - assert_eq!("'\"\\".escape_unicode(), - String::from_str("\\u{27}\\u{22}\\u{5c}")); - assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), - String::from_str("\\u{0}\\u{1}\\u{fe}\\u{ff}")); - assert_eq!("\u{100}\u{ffff}".escape_unicode(), - String::from_str("\\u{100}\\u{ffff}")); - assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), - String::from_str("\\u{10000}\\u{10ffff}")); - assert_eq!("ab\u{fb00}".escape_unicode(), - String::from_str("\\u{61}\\u{62}\\u{fb00}")); - assert_eq!("\u{1d4ea}\r".escape_unicode(), - String::from_str("\\u{1d4ea}\\u{d}")); - } - - #[test] - fn test_escape_default() { - assert_eq!("abc".escape_default(), String::from_str("abc")); - assert_eq!("a c".escape_default(), String::from_str("a c")); - assert_eq!("\r\n\t".escape_default(), String::from_str("\\r\\n\\t")); - assert_eq!("'\"\\".escape_default(), String::from_str("\\'\\\"\\\\")); - assert_eq!("\u{100}\u{ffff}".escape_default(), - String::from_str("\\u{100}\\u{ffff}")); - assert_eq!("\u{10000}\u{10ffff}".escape_default(), - String::from_str("\\u{10000}\\u{10ffff}")); - assert_eq!("ab\u{fb00}".escape_default(), - String::from_str("ab\\u{fb00}")); - assert_eq!("\u{1d4ea}\r".escape_default(), - String::from_str("\\u{1d4ea}\\r")); - } - - #[test] - fn test_total_ord() { - "1234".cmp("123") == Greater; - "123".cmp("1234") == Less; - "1234".cmp("1234") == Equal; - "12345555".cmp("123456") == Less; - "22".cmp("1234") == Greater; - } - - #[test] - fn test_char_range_at() { - let data = "b¢€𤭢𤭢€¢b"; - assert_eq!('b', data.char_range_at(0).ch); - assert_eq!('¢', data.char_range_at(1).ch); - assert_eq!('€', data.char_range_at(3).ch); - assert_eq!('𤭢', data.char_range_at(6).ch); - assert_eq!('𤭢', data.char_range_at(10).ch); - assert_eq!('€', data.char_range_at(14).ch); - assert_eq!('¢', data.char_range_at(17).ch); - assert_eq!('b', data.char_range_at(19).ch); - } - - #[test] - fn test_char_range_at_reverse_underflow() { - assert_eq!("abc".char_range_at_reverse(0).next, 0); - } - - #[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()); - } - - #[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(|c| ::core::char::from_u32(c)) { - let len = c.encode_utf8(&mut bytes).unwrap_or(0); - let s = ::core::str::from_utf8(&bytes[..len]).unwrap(); - 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(|c| ::core::char::from_u32(c)) { - let len = c.encode_utf8(&mut bytes).unwrap_or(0); - let s = ::core::str::from_utf8(&bytes[..len]).unwrap(); - 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_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_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_splitn_char_iterator() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.splitn(3, ' ').collect(); - assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); - - let split: Vec<&str> = data.splitn(3, |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(3, 'ä').collect(); - assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); - - let split: Vec<&str> = data.splitn(3, |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_words() { - let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; - let words: Vec<&str> = data.words().collect(); - assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) - } - - #[test] - fn test_nfd_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfd_chars().collect::(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "d\u{307}\u{1c4}"); - t!("\u{2026}", "\u{2026}"); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); - t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); - t!("a\u{301}", "a\u{301}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); - t!("\u{ac1c}", "\u{1100}\u{1162}"); - } - - #[test] - fn test_nfkd_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfkd_chars().collect::(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "d\u{307}DZ\u{30c}"); - t!("\u{2026}", "..."); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); - t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); - t!("a\u{301}", "a\u{301}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); - t!("\u{ac1c}", "\u{1100}\u{1162}"); - } - - #[test] - fn test_nfc_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfc_chars().collect::(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "\u{1e0b}\u{1c4}"); - t!("\u{2026}", "\u{2026}"); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); - t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); - t!("a\u{301}", "\u{e1}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{d4db}"); - t!("\u{ac1c}", "\u{ac1c}"); - t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); - } - - #[test] - fn test_nfkc_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfkc_chars().collect::(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "\u{1e0b}D\u{17d}"); - t!("\u{2026}", "..."); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); - t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); - t!("a\u{301}", "\u{e1}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{d4db}"); - t!("\u{ac1c}", "\u{ac1c}"); - t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); - } - - #[test] - fn test_lines() { - let data = "\nMäry häd ä little lämb\n\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 = "\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_graphemes() { - use core::iter::order; - // official Unicode test data - // from http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt - let test_same: [(_, &[_]); 325] = [ - ("\u{20}\u{20}", &["\u{20}", "\u{20}"]), - ("\u{20}\u{308}\u{20}", &["\u{20}\u{308}", "\u{20}"]), - ("\u{20}\u{D}", &["\u{20}", "\u{D}"]), - ("\u{20}\u{308}\u{D}", &["\u{20}\u{308}", "\u{D}"]), - ("\u{20}\u{A}", &["\u{20}", "\u{A}"]), - ("\u{20}\u{308}\u{A}", &["\u{20}\u{308}", "\u{A}"]), - ("\u{20}\u{1}", &["\u{20}", "\u{1}"]), - ("\u{20}\u{308}\u{1}", &["\u{20}\u{308}", "\u{1}"]), - ("\u{20}\u{300}", &["\u{20}\u{300}"]), - ("\u{20}\u{308}\u{300}", &["\u{20}\u{308}\u{300}"]), - ("\u{20}\u{1100}", &["\u{20}", "\u{1100}"]), - ("\u{20}\u{308}\u{1100}", &["\u{20}\u{308}", "\u{1100}"]), - ("\u{20}\u{1160}", &["\u{20}", "\u{1160}"]), - ("\u{20}\u{308}\u{1160}", &["\u{20}\u{308}", "\u{1160}"]), - ("\u{20}\u{11A8}", &["\u{20}", "\u{11A8}"]), - ("\u{20}\u{308}\u{11A8}", &["\u{20}\u{308}", "\u{11A8}"]), - ("\u{20}\u{AC00}", &["\u{20}", "\u{AC00}"]), - ("\u{20}\u{308}\u{AC00}", &["\u{20}\u{308}", "\u{AC00}"]), - ("\u{20}\u{AC01}", &["\u{20}", "\u{AC01}"]), - ("\u{20}\u{308}\u{AC01}", &["\u{20}\u{308}", "\u{AC01}"]), - ("\u{20}\u{1F1E6}", &["\u{20}", "\u{1F1E6}"]), - ("\u{20}\u{308}\u{1F1E6}", &["\u{20}\u{308}", "\u{1F1E6}"]), - ("\u{20}\u{378}", &["\u{20}", "\u{378}"]), - ("\u{20}\u{308}\u{378}", &["\u{20}\u{308}", "\u{378}"]), - ("\u{D}\u{20}", &["\u{D}", "\u{20}"]), - ("\u{D}\u{308}\u{20}", &["\u{D}", "\u{308}", "\u{20}"]), - ("\u{D}\u{D}", &["\u{D}", "\u{D}"]), - ("\u{D}\u{308}\u{D}", &["\u{D}", "\u{308}", "\u{D}"]), - ("\u{D}\u{A}", &["\u{D}\u{A}"]), - ("\u{D}\u{308}\u{A}", &["\u{D}", "\u{308}", "\u{A}"]), - ("\u{D}\u{1}", &["\u{D}", "\u{1}"]), - ("\u{D}\u{308}\u{1}", &["\u{D}", "\u{308}", "\u{1}"]), - ("\u{D}\u{300}", &["\u{D}", "\u{300}"]), - ("\u{D}\u{308}\u{300}", &["\u{D}", "\u{308}\u{300}"]), - ("\u{D}\u{903}", &["\u{D}", "\u{903}"]), - ("\u{D}\u{1100}", &["\u{D}", "\u{1100}"]), - ("\u{D}\u{308}\u{1100}", &["\u{D}", "\u{308}", "\u{1100}"]), - ("\u{D}\u{1160}", &["\u{D}", "\u{1160}"]), - ("\u{D}\u{308}\u{1160}", &["\u{D}", "\u{308}", "\u{1160}"]), - ("\u{D}\u{11A8}", &["\u{D}", "\u{11A8}"]), - ("\u{D}\u{308}\u{11A8}", &["\u{D}", "\u{308}", "\u{11A8}"]), - ("\u{D}\u{AC00}", &["\u{D}", "\u{AC00}"]), - ("\u{D}\u{308}\u{AC00}", &["\u{D}", "\u{308}", "\u{AC00}"]), - ("\u{D}\u{AC01}", &["\u{D}", "\u{AC01}"]), - ("\u{D}\u{308}\u{AC01}", &["\u{D}", "\u{308}", "\u{AC01}"]), - ("\u{D}\u{1F1E6}", &["\u{D}", "\u{1F1E6}"]), - ("\u{D}\u{308}\u{1F1E6}", &["\u{D}", "\u{308}", "\u{1F1E6}"]), - ("\u{D}\u{378}", &["\u{D}", "\u{378}"]), - ("\u{D}\u{308}\u{378}", &["\u{D}", "\u{308}", "\u{378}"]), - ("\u{A}\u{20}", &["\u{A}", "\u{20}"]), - ("\u{A}\u{308}\u{20}", &["\u{A}", "\u{308}", "\u{20}"]), - ("\u{A}\u{D}", &["\u{A}", "\u{D}"]), - ("\u{A}\u{308}\u{D}", &["\u{A}", "\u{308}", "\u{D}"]), - ("\u{A}\u{A}", &["\u{A}", "\u{A}"]), - ("\u{A}\u{308}\u{A}", &["\u{A}", "\u{308}", "\u{A}"]), - ("\u{A}\u{1}", &["\u{A}", "\u{1}"]), - ("\u{A}\u{308}\u{1}", &["\u{A}", "\u{308}", "\u{1}"]), - ("\u{A}\u{300}", &["\u{A}", "\u{300}"]), - ("\u{A}\u{308}\u{300}", &["\u{A}", "\u{308}\u{300}"]), - ("\u{A}\u{903}", &["\u{A}", "\u{903}"]), - ("\u{A}\u{1100}", &["\u{A}", "\u{1100}"]), - ("\u{A}\u{308}\u{1100}", &["\u{A}", "\u{308}", "\u{1100}"]), - ("\u{A}\u{1160}", &["\u{A}", "\u{1160}"]), - ("\u{A}\u{308}\u{1160}", &["\u{A}", "\u{308}", "\u{1160}"]), - ("\u{A}\u{11A8}", &["\u{A}", "\u{11A8}"]), - ("\u{A}\u{308}\u{11A8}", &["\u{A}", "\u{308}", "\u{11A8}"]), - ("\u{A}\u{AC00}", &["\u{A}", "\u{AC00}"]), - ("\u{A}\u{308}\u{AC00}", &["\u{A}", "\u{308}", "\u{AC00}"]), - ("\u{A}\u{AC01}", &["\u{A}", "\u{AC01}"]), - ("\u{A}\u{308}\u{AC01}", &["\u{A}", "\u{308}", "\u{AC01}"]), - ("\u{A}\u{1F1E6}", &["\u{A}", "\u{1F1E6}"]), - ("\u{A}\u{308}\u{1F1E6}", &["\u{A}", "\u{308}", "\u{1F1E6}"]), - ("\u{A}\u{378}", &["\u{A}", "\u{378}"]), - ("\u{A}\u{308}\u{378}", &["\u{A}", "\u{308}", "\u{378}"]), - ("\u{1}\u{20}", &["\u{1}", "\u{20}"]), - ("\u{1}\u{308}\u{20}", &["\u{1}", "\u{308}", "\u{20}"]), - ("\u{1}\u{D}", &["\u{1}", "\u{D}"]), - ("\u{1}\u{308}\u{D}", &["\u{1}", "\u{308}", "\u{D}"]), - ("\u{1}\u{A}", &["\u{1}", "\u{A}"]), - ("\u{1}\u{308}\u{A}", &["\u{1}", "\u{308}", "\u{A}"]), - ("\u{1}\u{1}", &["\u{1}", "\u{1}"]), - ("\u{1}\u{308}\u{1}", &["\u{1}", "\u{308}", "\u{1}"]), - ("\u{1}\u{300}", &["\u{1}", "\u{300}"]), - ("\u{1}\u{308}\u{300}", &["\u{1}", "\u{308}\u{300}"]), - ("\u{1}\u{903}", &["\u{1}", "\u{903}"]), - ("\u{1}\u{1100}", &["\u{1}", "\u{1100}"]), - ("\u{1}\u{308}\u{1100}", &["\u{1}", "\u{308}", "\u{1100}"]), - ("\u{1}\u{1160}", &["\u{1}", "\u{1160}"]), - ("\u{1}\u{308}\u{1160}", &["\u{1}", "\u{308}", "\u{1160}"]), - ("\u{1}\u{11A8}", &["\u{1}", "\u{11A8}"]), - ("\u{1}\u{308}\u{11A8}", &["\u{1}", "\u{308}", "\u{11A8}"]), - ("\u{1}\u{AC00}", &["\u{1}", "\u{AC00}"]), - ("\u{1}\u{308}\u{AC00}", &["\u{1}", "\u{308}", "\u{AC00}"]), - ("\u{1}\u{AC01}", &["\u{1}", "\u{AC01}"]), - ("\u{1}\u{308}\u{AC01}", &["\u{1}", "\u{308}", "\u{AC01}"]), - ("\u{1}\u{1F1E6}", &["\u{1}", "\u{1F1E6}"]), - ("\u{1}\u{308}\u{1F1E6}", &["\u{1}", "\u{308}", "\u{1F1E6}"]), - ("\u{1}\u{378}", &["\u{1}", "\u{378}"]), - ("\u{1}\u{308}\u{378}", &["\u{1}", "\u{308}", "\u{378}"]), - ("\u{300}\u{20}", &["\u{300}", "\u{20}"]), - ("\u{300}\u{308}\u{20}", &["\u{300}\u{308}", "\u{20}"]), - ("\u{300}\u{D}", &["\u{300}", "\u{D}"]), - ("\u{300}\u{308}\u{D}", &["\u{300}\u{308}", "\u{D}"]), - ("\u{300}\u{A}", &["\u{300}", "\u{A}"]), - ("\u{300}\u{308}\u{A}", &["\u{300}\u{308}", "\u{A}"]), - ("\u{300}\u{1}", &["\u{300}", "\u{1}"]), - ("\u{300}\u{308}\u{1}", &["\u{300}\u{308}", "\u{1}"]), - ("\u{300}\u{300}", &["\u{300}\u{300}"]), - ("\u{300}\u{308}\u{300}", &["\u{300}\u{308}\u{300}"]), - ("\u{300}\u{1100}", &["\u{300}", "\u{1100}"]), - ("\u{300}\u{308}\u{1100}", &["\u{300}\u{308}", "\u{1100}"]), - ("\u{300}\u{1160}", &["\u{300}", "\u{1160}"]), - ("\u{300}\u{308}\u{1160}", &["\u{300}\u{308}", "\u{1160}"]), - ("\u{300}\u{11A8}", &["\u{300}", "\u{11A8}"]), - ("\u{300}\u{308}\u{11A8}", &["\u{300}\u{308}", "\u{11A8}"]), - ("\u{300}\u{AC00}", &["\u{300}", "\u{AC00}"]), - ("\u{300}\u{308}\u{AC00}", &["\u{300}\u{308}", "\u{AC00}"]), - ("\u{300}\u{AC01}", &["\u{300}", "\u{AC01}"]), - ("\u{300}\u{308}\u{AC01}", &["\u{300}\u{308}", "\u{AC01}"]), - ("\u{300}\u{1F1E6}", &["\u{300}", "\u{1F1E6}"]), - ("\u{300}\u{308}\u{1F1E6}", &["\u{300}\u{308}", "\u{1F1E6}"]), - ("\u{300}\u{378}", &["\u{300}", "\u{378}"]), - ("\u{300}\u{308}\u{378}", &["\u{300}\u{308}", "\u{378}"]), - ("\u{903}\u{20}", &["\u{903}", "\u{20}"]), - ("\u{903}\u{308}\u{20}", &["\u{903}\u{308}", "\u{20}"]), - ("\u{903}\u{D}", &["\u{903}", "\u{D}"]), - ("\u{903}\u{308}\u{D}", &["\u{903}\u{308}", "\u{D}"]), - ("\u{903}\u{A}", &["\u{903}", "\u{A}"]), - ("\u{903}\u{308}\u{A}", &["\u{903}\u{308}", "\u{A}"]), - ("\u{903}\u{1}", &["\u{903}", "\u{1}"]), - ("\u{903}\u{308}\u{1}", &["\u{903}\u{308}", "\u{1}"]), - ("\u{903}\u{300}", &["\u{903}\u{300}"]), - ("\u{903}\u{308}\u{300}", &["\u{903}\u{308}\u{300}"]), - ("\u{903}\u{1100}", &["\u{903}", "\u{1100}"]), - ("\u{903}\u{308}\u{1100}", &["\u{903}\u{308}", "\u{1100}"]), - ("\u{903}\u{1160}", &["\u{903}", "\u{1160}"]), - ("\u{903}\u{308}\u{1160}", &["\u{903}\u{308}", "\u{1160}"]), - ("\u{903}\u{11A8}", &["\u{903}", "\u{11A8}"]), - ("\u{903}\u{308}\u{11A8}", &["\u{903}\u{308}", "\u{11A8}"]), - ("\u{903}\u{AC00}", &["\u{903}", "\u{AC00}"]), - ("\u{903}\u{308}\u{AC00}", &["\u{903}\u{308}", "\u{AC00}"]), - ("\u{903}\u{AC01}", &["\u{903}", "\u{AC01}"]), - ("\u{903}\u{308}\u{AC01}", &["\u{903}\u{308}", "\u{AC01}"]), - ("\u{903}\u{1F1E6}", &["\u{903}", "\u{1F1E6}"]), - ("\u{903}\u{308}\u{1F1E6}", &["\u{903}\u{308}", "\u{1F1E6}"]), - ("\u{903}\u{378}", &["\u{903}", "\u{378}"]), - ("\u{903}\u{308}\u{378}", &["\u{903}\u{308}", "\u{378}"]), - ("\u{1100}\u{20}", &["\u{1100}", "\u{20}"]), - ("\u{1100}\u{308}\u{20}", &["\u{1100}\u{308}", "\u{20}"]), - ("\u{1100}\u{D}", &["\u{1100}", "\u{D}"]), - ("\u{1100}\u{308}\u{D}", &["\u{1100}\u{308}", "\u{D}"]), - ("\u{1100}\u{A}", &["\u{1100}", "\u{A}"]), - ("\u{1100}\u{308}\u{A}", &["\u{1100}\u{308}", "\u{A}"]), - ("\u{1100}\u{1}", &["\u{1100}", "\u{1}"]), - ("\u{1100}\u{308}\u{1}", &["\u{1100}\u{308}", "\u{1}"]), - ("\u{1100}\u{300}", &["\u{1100}\u{300}"]), - ("\u{1100}\u{308}\u{300}", &["\u{1100}\u{308}\u{300}"]), - ("\u{1100}\u{1100}", &["\u{1100}\u{1100}"]), - ("\u{1100}\u{308}\u{1100}", &["\u{1100}\u{308}", "\u{1100}"]), - ("\u{1100}\u{1160}", &["\u{1100}\u{1160}"]), - ("\u{1100}\u{308}\u{1160}", &["\u{1100}\u{308}", "\u{1160}"]), - ("\u{1100}\u{11A8}", &["\u{1100}", "\u{11A8}"]), - ("\u{1100}\u{308}\u{11A8}", &["\u{1100}\u{308}", "\u{11A8}"]), - ("\u{1100}\u{AC00}", &["\u{1100}\u{AC00}"]), - ("\u{1100}\u{308}\u{AC00}", &["\u{1100}\u{308}", "\u{AC00}"]), - ("\u{1100}\u{AC01}", &["\u{1100}\u{AC01}"]), - ("\u{1100}\u{308}\u{AC01}", &["\u{1100}\u{308}", "\u{AC01}"]), - ("\u{1100}\u{1F1E6}", &["\u{1100}", "\u{1F1E6}"]), - ("\u{1100}\u{308}\u{1F1E6}", &["\u{1100}\u{308}", "\u{1F1E6}"]), - ("\u{1100}\u{378}", &["\u{1100}", "\u{378}"]), - ("\u{1100}\u{308}\u{378}", &["\u{1100}\u{308}", "\u{378}"]), - ("\u{1160}\u{20}", &["\u{1160}", "\u{20}"]), - ("\u{1160}\u{308}\u{20}", &["\u{1160}\u{308}", "\u{20}"]), - ("\u{1160}\u{D}", &["\u{1160}", "\u{D}"]), - ("\u{1160}\u{308}\u{D}", &["\u{1160}\u{308}", "\u{D}"]), - ("\u{1160}\u{A}", &["\u{1160}", "\u{A}"]), - ("\u{1160}\u{308}\u{A}", &["\u{1160}\u{308}", "\u{A}"]), - ("\u{1160}\u{1}", &["\u{1160}", "\u{1}"]), - ("\u{1160}\u{308}\u{1}", &["\u{1160}\u{308}", "\u{1}"]), - ("\u{1160}\u{300}", &["\u{1160}\u{300}"]), - ("\u{1160}\u{308}\u{300}", &["\u{1160}\u{308}\u{300}"]), - ("\u{1160}\u{1100}", &["\u{1160}", "\u{1100}"]), - ("\u{1160}\u{308}\u{1100}", &["\u{1160}\u{308}", "\u{1100}"]), - ("\u{1160}\u{1160}", &["\u{1160}\u{1160}"]), - ("\u{1160}\u{308}\u{1160}", &["\u{1160}\u{308}", "\u{1160}"]), - ("\u{1160}\u{11A8}", &["\u{1160}\u{11A8}"]), - ("\u{1160}\u{308}\u{11A8}", &["\u{1160}\u{308}", "\u{11A8}"]), - ("\u{1160}\u{AC00}", &["\u{1160}", "\u{AC00}"]), - ("\u{1160}\u{308}\u{AC00}", &["\u{1160}\u{308}", "\u{AC00}"]), - ("\u{1160}\u{AC01}", &["\u{1160}", "\u{AC01}"]), - ("\u{1160}\u{308}\u{AC01}", &["\u{1160}\u{308}", "\u{AC01}"]), - ("\u{1160}\u{1F1E6}", &["\u{1160}", "\u{1F1E6}"]), - ("\u{1160}\u{308}\u{1F1E6}", &["\u{1160}\u{308}", "\u{1F1E6}"]), - ("\u{1160}\u{378}", &["\u{1160}", "\u{378}"]), - ("\u{1160}\u{308}\u{378}", &["\u{1160}\u{308}", "\u{378}"]), - ("\u{11A8}\u{20}", &["\u{11A8}", "\u{20}"]), - ("\u{11A8}\u{308}\u{20}", &["\u{11A8}\u{308}", "\u{20}"]), - ("\u{11A8}\u{D}", &["\u{11A8}", "\u{D}"]), - ("\u{11A8}\u{308}\u{D}", &["\u{11A8}\u{308}", "\u{D}"]), - ("\u{11A8}\u{A}", &["\u{11A8}", "\u{A}"]), - ("\u{11A8}\u{308}\u{A}", &["\u{11A8}\u{308}", "\u{A}"]), - ("\u{11A8}\u{1}", &["\u{11A8}", "\u{1}"]), - ("\u{11A8}\u{308}\u{1}", &["\u{11A8}\u{308}", "\u{1}"]), - ("\u{11A8}\u{300}", &["\u{11A8}\u{300}"]), - ("\u{11A8}\u{308}\u{300}", &["\u{11A8}\u{308}\u{300}"]), - ("\u{11A8}\u{1100}", &["\u{11A8}", "\u{1100}"]), - ("\u{11A8}\u{308}\u{1100}", &["\u{11A8}\u{308}", "\u{1100}"]), - ("\u{11A8}\u{1160}", &["\u{11A8}", "\u{1160}"]), - ("\u{11A8}\u{308}\u{1160}", &["\u{11A8}\u{308}", "\u{1160}"]), - ("\u{11A8}\u{11A8}", &["\u{11A8}\u{11A8}"]), - ("\u{11A8}\u{308}\u{11A8}", &["\u{11A8}\u{308}", "\u{11A8}"]), - ("\u{11A8}\u{AC00}", &["\u{11A8}", "\u{AC00}"]), - ("\u{11A8}\u{308}\u{AC00}", &["\u{11A8}\u{308}", "\u{AC00}"]), - ("\u{11A8}\u{AC01}", &["\u{11A8}", "\u{AC01}"]), - ("\u{11A8}\u{308}\u{AC01}", &["\u{11A8}\u{308}", "\u{AC01}"]), - ("\u{11A8}\u{1F1E6}", &["\u{11A8}", "\u{1F1E6}"]), - ("\u{11A8}\u{308}\u{1F1E6}", &["\u{11A8}\u{308}", "\u{1F1E6}"]), - ("\u{11A8}\u{378}", &["\u{11A8}", "\u{378}"]), - ("\u{11A8}\u{308}\u{378}", &["\u{11A8}\u{308}", "\u{378}"]), - ("\u{AC00}\u{20}", &["\u{AC00}", "\u{20}"]), - ("\u{AC00}\u{308}\u{20}", &["\u{AC00}\u{308}", "\u{20}"]), - ("\u{AC00}\u{D}", &["\u{AC00}", "\u{D}"]), - ("\u{AC00}\u{308}\u{D}", &["\u{AC00}\u{308}", "\u{D}"]), - ("\u{AC00}\u{A}", &["\u{AC00}", "\u{A}"]), - ("\u{AC00}\u{308}\u{A}", &["\u{AC00}\u{308}", "\u{A}"]), - ("\u{AC00}\u{1}", &["\u{AC00}", "\u{1}"]), - ("\u{AC00}\u{308}\u{1}", &["\u{AC00}\u{308}", "\u{1}"]), - ("\u{AC00}\u{300}", &["\u{AC00}\u{300}"]), - ("\u{AC00}\u{308}\u{300}", &["\u{AC00}\u{308}\u{300}"]), - ("\u{AC00}\u{1100}", &["\u{AC00}", "\u{1100}"]), - ("\u{AC00}\u{308}\u{1100}", &["\u{AC00}\u{308}", "\u{1100}"]), - ("\u{AC00}\u{1160}", &["\u{AC00}\u{1160}"]), - ("\u{AC00}\u{308}\u{1160}", &["\u{AC00}\u{308}", "\u{1160}"]), - ("\u{AC00}\u{11A8}", &["\u{AC00}\u{11A8}"]), - ("\u{AC00}\u{308}\u{11A8}", &["\u{AC00}\u{308}", "\u{11A8}"]), - ("\u{AC00}\u{AC00}", &["\u{AC00}", "\u{AC00}"]), - ("\u{AC00}\u{308}\u{AC00}", &["\u{AC00}\u{308}", "\u{AC00}"]), - ("\u{AC00}\u{AC01}", &["\u{AC00}", "\u{AC01}"]), - ("\u{AC00}\u{308}\u{AC01}", &["\u{AC00}\u{308}", "\u{AC01}"]), - ("\u{AC00}\u{1F1E6}", &["\u{AC00}", "\u{1F1E6}"]), - ("\u{AC00}\u{308}\u{1F1E6}", &["\u{AC00}\u{308}", "\u{1F1E6}"]), - ("\u{AC00}\u{378}", &["\u{AC00}", "\u{378}"]), - ("\u{AC00}\u{308}\u{378}", &["\u{AC00}\u{308}", "\u{378}"]), - ("\u{AC01}\u{20}", &["\u{AC01}", "\u{20}"]), - ("\u{AC01}\u{308}\u{20}", &["\u{AC01}\u{308}", "\u{20}"]), - ("\u{AC01}\u{D}", &["\u{AC01}", "\u{D}"]), - ("\u{AC01}\u{308}\u{D}", &["\u{AC01}\u{308}", "\u{D}"]), - ("\u{AC01}\u{A}", &["\u{AC01}", "\u{A}"]), - ("\u{AC01}\u{308}\u{A}", &["\u{AC01}\u{308}", "\u{A}"]), - ("\u{AC01}\u{1}", &["\u{AC01}", "\u{1}"]), - ("\u{AC01}\u{308}\u{1}", &["\u{AC01}\u{308}", "\u{1}"]), - ("\u{AC01}\u{300}", &["\u{AC01}\u{300}"]), - ("\u{AC01}\u{308}\u{300}", &["\u{AC01}\u{308}\u{300}"]), - ("\u{AC01}\u{1100}", &["\u{AC01}", "\u{1100}"]), - ("\u{AC01}\u{308}\u{1100}", &["\u{AC01}\u{308}", "\u{1100}"]), - ("\u{AC01}\u{1160}", &["\u{AC01}", "\u{1160}"]), - ("\u{AC01}\u{308}\u{1160}", &["\u{AC01}\u{308}", "\u{1160}"]), - ("\u{AC01}\u{11A8}", &["\u{AC01}\u{11A8}"]), - ("\u{AC01}\u{308}\u{11A8}", &["\u{AC01}\u{308}", "\u{11A8}"]), - ("\u{AC01}\u{AC00}", &["\u{AC01}", "\u{AC00}"]), - ("\u{AC01}\u{308}\u{AC00}", &["\u{AC01}\u{308}", "\u{AC00}"]), - ("\u{AC01}\u{AC01}", &["\u{AC01}", "\u{AC01}"]), - ("\u{AC01}\u{308}\u{AC01}", &["\u{AC01}\u{308}", "\u{AC01}"]), - ("\u{AC01}\u{1F1E6}", &["\u{AC01}", "\u{1F1E6}"]), - ("\u{AC01}\u{308}\u{1F1E6}", &["\u{AC01}\u{308}", "\u{1F1E6}"]), - ("\u{AC01}\u{378}", &["\u{AC01}", "\u{378}"]), - ("\u{AC01}\u{308}\u{378}", &["\u{AC01}\u{308}", "\u{378}"]), - ("\u{1F1E6}\u{20}", &["\u{1F1E6}", "\u{20}"]), - ("\u{1F1E6}\u{308}\u{20}", &["\u{1F1E6}\u{308}", "\u{20}"]), - ("\u{1F1E6}\u{D}", &["\u{1F1E6}", "\u{D}"]), - ("\u{1F1E6}\u{308}\u{D}", &["\u{1F1E6}\u{308}", "\u{D}"]), - ("\u{1F1E6}\u{A}", &["\u{1F1E6}", "\u{A}"]), - ("\u{1F1E6}\u{308}\u{A}", &["\u{1F1E6}\u{308}", "\u{A}"]), - ("\u{1F1E6}\u{1}", &["\u{1F1E6}", "\u{1}"]), - ("\u{1F1E6}\u{308}\u{1}", &["\u{1F1E6}\u{308}", "\u{1}"]), - ("\u{1F1E6}\u{300}", &["\u{1F1E6}\u{300}"]), - ("\u{1F1E6}\u{308}\u{300}", &["\u{1F1E6}\u{308}\u{300}"]), - ("\u{1F1E6}\u{1100}", &["\u{1F1E6}", "\u{1100}"]), - ("\u{1F1E6}\u{308}\u{1100}", &["\u{1F1E6}\u{308}", "\u{1100}"]), - ("\u{1F1E6}\u{1160}", &["\u{1F1E6}", "\u{1160}"]), - ("\u{1F1E6}\u{308}\u{1160}", &["\u{1F1E6}\u{308}", "\u{1160}"]), - ("\u{1F1E6}\u{11A8}", &["\u{1F1E6}", "\u{11A8}"]), - ("\u{1F1E6}\u{308}\u{11A8}", &["\u{1F1E6}\u{308}", "\u{11A8}"]), - ("\u{1F1E6}\u{AC00}", &["\u{1F1E6}", "\u{AC00}"]), - ("\u{1F1E6}\u{308}\u{AC00}", &["\u{1F1E6}\u{308}", "\u{AC00}"]), - ("\u{1F1E6}\u{AC01}", &["\u{1F1E6}", "\u{AC01}"]), - ("\u{1F1E6}\u{308}\u{AC01}", &["\u{1F1E6}\u{308}", "\u{AC01}"]), - ("\u{1F1E6}\u{1F1E6}", &["\u{1F1E6}\u{1F1E6}"]), - ("\u{1F1E6}\u{308}\u{1F1E6}", &["\u{1F1E6}\u{308}", "\u{1F1E6}"]), - ("\u{1F1E6}\u{378}", &["\u{1F1E6}", "\u{378}"]), - ("\u{1F1E6}\u{308}\u{378}", &["\u{1F1E6}\u{308}", "\u{378}"]), - ("\u{378}\u{20}", &["\u{378}", "\u{20}"]), - ("\u{378}\u{308}\u{20}", &["\u{378}\u{308}", "\u{20}"]), - ("\u{378}\u{D}", &["\u{378}", "\u{D}"]), - ("\u{378}\u{308}\u{D}", &["\u{378}\u{308}", "\u{D}"]), - ("\u{378}\u{A}", &["\u{378}", "\u{A}"]), - ("\u{378}\u{308}\u{A}", &["\u{378}\u{308}", "\u{A}"]), - ("\u{378}\u{1}", &["\u{378}", "\u{1}"]), - ("\u{378}\u{308}\u{1}", &["\u{378}\u{308}", "\u{1}"]), - ("\u{378}\u{300}", &["\u{378}\u{300}"]), - ("\u{378}\u{308}\u{300}", &["\u{378}\u{308}\u{300}"]), - ("\u{378}\u{1100}", &["\u{378}", "\u{1100}"]), - ("\u{378}\u{308}\u{1100}", &["\u{378}\u{308}", "\u{1100}"]), - ("\u{378}\u{1160}", &["\u{378}", "\u{1160}"]), - ("\u{378}\u{308}\u{1160}", &["\u{378}\u{308}", "\u{1160}"]), - ("\u{378}\u{11A8}", &["\u{378}", "\u{11A8}"]), - ("\u{378}\u{308}\u{11A8}", &["\u{378}\u{308}", "\u{11A8}"]), - ("\u{378}\u{AC00}", &["\u{378}", "\u{AC00}"]), - ("\u{378}\u{308}\u{AC00}", &["\u{378}\u{308}", "\u{AC00}"]), - ("\u{378}\u{AC01}", &["\u{378}", "\u{AC01}"]), - ("\u{378}\u{308}\u{AC01}", &["\u{378}\u{308}", "\u{AC01}"]), - ("\u{378}\u{1F1E6}", &["\u{378}", "\u{1F1E6}"]), - ("\u{378}\u{308}\u{1F1E6}", &["\u{378}\u{308}", "\u{1F1E6}"]), - ("\u{378}\u{378}", &["\u{378}", "\u{378}"]), - ("\u{378}\u{308}\u{378}", &["\u{378}\u{308}", "\u{378}"]), - ("\u{61}\u{1F1E6}\u{62}", &["\u{61}", "\u{1F1E6}", "\u{62}"]), - ("\u{1F1F7}\u{1F1FA}", &["\u{1F1F7}\u{1F1FA}"]), - ("\u{1F1F7}\u{1F1FA}\u{1F1F8}", &["\u{1F1F7}\u{1F1FA}\u{1F1F8}"]), - ("\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}", - &["\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}"]), - ("\u{1F1F7}\u{1F1FA}\u{200B}\u{1F1F8}\u{1F1EA}", - &["\u{1F1F7}\u{1F1FA}", "\u{200B}", "\u{1F1F8}\u{1F1EA}"]), - ("\u{1F1E6}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{1F1E7}\u{1F1E8}"]), - ("\u{1F1E6}\u{200D}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{200D}", - "\u{1F1E7}\u{1F1E8}"]), - ("\u{1F1E6}\u{1F1E7}\u{200D}\u{1F1E8}", - &["\u{1F1E6}\u{1F1E7}\u{200D}", "\u{1F1E8}"]), - ("\u{20}\u{200D}\u{646}", &["\u{20}\u{200D}", "\u{646}"]), - ("\u{646}\u{200D}\u{20}", &["\u{646}\u{200D}", "\u{20}"]), - ]; - - let test_diff: [(_, &[_], &[_]); 23] = [ - ("\u{20}\u{903}", &["\u{20}\u{903}"], &["\u{20}", "\u{903}"]), ("\u{20}\u{308}\u{903}", - &["\u{20}\u{308}\u{903}"], &["\u{20}\u{308}", "\u{903}"]), ("\u{D}\u{308}\u{903}", - &["\u{D}", "\u{308}\u{903}"], &["\u{D}", "\u{308}", "\u{903}"]), ("\u{A}\u{308}\u{903}", - &["\u{A}", "\u{308}\u{903}"], &["\u{A}", "\u{308}", "\u{903}"]), ("\u{1}\u{308}\u{903}", - &["\u{1}", "\u{308}\u{903}"], &["\u{1}", "\u{308}", "\u{903}"]), ("\u{300}\u{903}", - &["\u{300}\u{903}"], &["\u{300}", "\u{903}"]), ("\u{300}\u{308}\u{903}", - &["\u{300}\u{308}\u{903}"], &["\u{300}\u{308}", "\u{903}"]), ("\u{903}\u{903}", - &["\u{903}\u{903}"], &["\u{903}", "\u{903}"]), ("\u{903}\u{308}\u{903}", - &["\u{903}\u{308}\u{903}"], &["\u{903}\u{308}", "\u{903}"]), ("\u{1100}\u{903}", - &["\u{1100}\u{903}"], &["\u{1100}", "\u{903}"]), ("\u{1100}\u{308}\u{903}", - &["\u{1100}\u{308}\u{903}"], &["\u{1100}\u{308}", "\u{903}"]), ("\u{1160}\u{903}", - &["\u{1160}\u{903}"], &["\u{1160}", "\u{903}"]), ("\u{1160}\u{308}\u{903}", - &["\u{1160}\u{308}\u{903}"], &["\u{1160}\u{308}", "\u{903}"]), ("\u{11A8}\u{903}", - &["\u{11A8}\u{903}"], &["\u{11A8}", "\u{903}"]), ("\u{11A8}\u{308}\u{903}", - &["\u{11A8}\u{308}\u{903}"], &["\u{11A8}\u{308}", "\u{903}"]), ("\u{AC00}\u{903}", - &["\u{AC00}\u{903}"], &["\u{AC00}", "\u{903}"]), ("\u{AC00}\u{308}\u{903}", - &["\u{AC00}\u{308}\u{903}"], &["\u{AC00}\u{308}", "\u{903}"]), ("\u{AC01}\u{903}", - &["\u{AC01}\u{903}"], &["\u{AC01}", "\u{903}"]), ("\u{AC01}\u{308}\u{903}", - &["\u{AC01}\u{308}\u{903}"], &["\u{AC01}\u{308}", "\u{903}"]), ("\u{1F1E6}\u{903}", - &["\u{1F1E6}\u{903}"], &["\u{1F1E6}", "\u{903}"]), ("\u{1F1E6}\u{308}\u{903}", - &["\u{1F1E6}\u{308}\u{903}"], &["\u{1F1E6}\u{308}", "\u{903}"]), ("\u{378}\u{903}", - &["\u{378}\u{903}"], &["\u{378}", "\u{903}"]), ("\u{378}\u{308}\u{903}", - &["\u{378}\u{308}\u{903}"], &["\u{378}\u{308}", "\u{903}"]), - ]; - - for &(s, g) in &test_same[..] { - // test forward iterator - assert!(order::equals(s.graphemes(true), g.iter().cloned())); - assert!(order::equals(s.graphemes(false), g.iter().cloned())); - - // test reverse iterator - assert!(order::equals(s.graphemes(true).rev(), g.iter().rev().cloned())); - assert!(order::equals(s.graphemes(false).rev(), g.iter().rev().cloned())); - } - - for &(s, gt, gf) in &test_diff { - // test forward iterator - assert!(order::equals(s.graphemes(true), gt.iter().cloned())); - assert!(order::equals(s.graphemes(false), gf.iter().cloned())); - - // test reverse iterator - assert!(order::equals(s.graphemes(true).rev(), gt.iter().rev().cloned())); - assert!(order::equals(s.graphemes(false).rev(), gf.iter().rev().cloned())); - } - - // test the indices iterators - let s = "a̐éö̲\r\n"; - let gr_inds = s.grapheme_indices(true).collect::>(); - let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; - assert_eq!(gr_inds, b); - let gr_inds = s.grapheme_indices(true).rev().collect::>(); - let b: &[_] = &[(11, "\r\n"), (6, "ö̲"), (3, "é"), (0, "a̐")]; - assert_eq!(gr_inds, b); - let mut gr_inds_iter = s.grapheme_indices(true); - { - let gr_inds = gr_inds_iter.by_ref(); - let e1 = gr_inds.size_hint(); - assert_eq!(e1, (1, Some(13))); - let c = gr_inds.count(); - assert_eq!(c, 4); - } - let e2 = gr_inds_iter.size_hint(); - assert_eq!(e2, (0, Some(0))); - - // make sure the reverse iterator does the right thing with "\n" at beginning of string - let s = "\n\r\n\r"; - let gr = s.graphemes(true).rev().collect::>(); - let b: &[_] = &["\r", "\r\n", "\n"]; - assert_eq!(gr, b); - } - - #[test] - fn test_split_strator() { - fn t(s: &str, sep: &str, u: &[&str]) { - let v: Vec<&str> = s.split_str(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 core::default::Default; - fn t() { - let s: S = Default::default(); - assert_eq!(s.as_slice(), ""); - } - - t::<&str>(); - t::(); - } - - #[test] - fn test_str_container() { - fn sum_len(v: &[&str]) -> usize { - v.iter().map(|x| x.len()).sum() - } - - let s = String::from_str("01234"); - assert_eq!(5, sum_len(&["012", "", "34"])); - assert_eq!(5, sum_len(&[&String::from_str("01"), - &String::from_str("2"), - &String::from_str("34"), - &String::from_str("")])); - 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_eq!(from_utf8(xs), Err(Utf8Error::TooShort)); - } -} - -#[cfg(test)] -mod bench { - use super::*; - use prelude::{SliceExt, IteratorExt, SliceConcatExt}; - use test::Bencher; - use test::black_box; - - #[bench] - fn char_iterator(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| s.chars().count()); - } - - #[bench] - fn char_iterator_for(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| { - for ch in s.chars() { black_box(ch); } - }); - } - - #[bench] - fn char_iterator_ascii(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb"; - - b.iter(|| s.chars().count()); - } - - #[bench] - fn char_iterator_rev(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| s.chars().rev().count()); - } - - #[bench] - fn char_iterator_rev_for(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| { - for ch in s.chars().rev() { black_box(ch); } - }); - } - - #[bench] - fn char_indicesator(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let len = s.chars().count(); - - b.iter(|| assert_eq!(s.char_indices().count(), len)); - } - - #[bench] - fn char_indicesator_rev(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let len = s.chars().count(); - - b.iter(|| assert_eq!(s.char_indices().rev().count(), len)); - } - - #[bench] - fn split_unicode_ascii(b: &mut Bencher) { - let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; - - b.iter(|| assert_eq!(s.split('V').count(), 3)); - } - - #[bench] - fn split_ascii(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - - b.iter(|| assert_eq!(s.split(' ').count(), len)); - } - - #[bench] - fn split_extern_fn(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - fn pred(c: char) -> bool { c == ' ' } - - b.iter(|| assert_eq!(s.split(pred).count(), len)); - } - - #[bench] - fn split_closure(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - - b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len)); - } - - #[bench] - fn split_slice(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - - let c: &[char] = &[' ']; - b.iter(|| assert_eq!(s.split(c).count(), len)); - } - - #[bench] - fn bench_connect(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let sep = "→"; - let v = vec![s, s, s, s, s, s, s, s, s, s]; - b.iter(|| { - assert_eq!(v.connect(sep).len(), s.len() * 10 + sep.len() * 9); - }) - } - - #[bench] - fn bench_contains_short_short(b: &mut Bencher) { - let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - let needle = "sit"; - - b.iter(|| { - assert!(haystack.contains(needle)); - }) - } - - #[bench] - fn bench_contains_short_long(b: &mut Bencher) { - let haystack = "\ -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. - -In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ -sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ -diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ -lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ -eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ -interdum. Curabitur ut nisi justo. - -Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ -mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ -lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ -est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ -felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ -ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ -feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ -Aliquam sit amet placerat lorem. - -Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ -mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ -Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ -lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ -suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ -cursus accumsan. - -Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ -feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ -vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ -leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ -malesuada sollicitudin quam eu fermentum."; - let needle = "english"; - - b.iter(|| { - assert!(!haystack.contains(needle)); - }) - } - - #[bench] - fn bench_contains_bad_naive(b: &mut Bencher) { - let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let needle = "aaaaaaaab"; - - b.iter(|| { - assert!(!haystack.contains(needle)); - }) - } - - #[bench] - fn bench_contains_equal(b: &mut Bencher) { - let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - - b.iter(|| { - assert!(haystack.contains(needle)); - }) - } -} diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 64dec9731ec21..6d1b929cf601c 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1014,450 +1014,3 @@ impl fmt::Write for String { Ok(()) } } - -#[cfg(test)] -mod tests { - use prelude::*; - use test::Bencher; - - use str::Utf8Error; - use core::iter::repeat; - use super::{as_string, CowString}; - - #[test] - fn test_as_string() { - let x = "foo"; - assert_eq!(x, &**as_string(x)); - } - - #[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_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_str("hello")); - - let xs = "ศไทย中华Việt Nam".as_bytes().to_vec(); - assert_eq!(String::from_utf8(xs).unwrap(), - String::from_str("ศไทย中华Việt Nam")); - - let xs = b"hello\xFF".to_vec(); - let err = String::from_utf8(xs).err().unwrap(); - assert_eq!(err.utf8_error(), Utf8Error::TooShort); - assert_eq!(err.into_bytes(), b"hello\xff".to_vec()); - } - - #[test] - fn test_from_utf8_lossy() { - let xs = b"hello"; - let ys: CowString = "hello".into_cow(); - assert_eq!(String::from_utf8_lossy(xs), ys); - - let xs = "ศไทย中华Việt Nam".as_bytes(); - let ys: CowString = "ศไทย中华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_str("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_str("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_str("\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_str("\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_str("\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_str("\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_str("\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_str("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"), - vec![0xd800, 0xdf45, 0xd800, 0xdf3f, - 0xd800, 0xdf3b, 0xd800, 0xdf46, - 0xd800, 0xdf39, 0xd800, 0xdf3b, - 0xd800, 0xdf30, 0x000a]), - - (String::from_str("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"), - vec![0xd801, 0xdc12, 0xd801, - 0xdc49, 0xd801, 0xdc2e, 0xd801, - 0xdc40, 0xd801, 0xdc32, 0xd801, - 0xdc4b, 0x0020, 0xd801, 0xdc0f, - 0xd801, 0xdc32, 0xd801, 0xdc4d, - 0x000a]), - - (String::from_str("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\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_str("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\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_str("\u{20000}"), - vec![0xD840, 0xDC00])]; - - for p in &pairs { - let (s, u) = (*p).clone(); - let s_as_utf16 = s.utf16_units().collect::>(); - let u_as_string = String::from_utf16(&u).unwrap(); - - assert!(::unicode::str::is_utf16(&u)); - 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.utf16_units().collect::>(), 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_str("\u{FFFD}")); - // lead + lead - assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), - String::from_str("\u{FFFD}\u{FFFD}")); - - // isolated trail - assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from_str("a\u{FFFD}")); - - // general - assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]), - String::from_str("\u{FFFD}𐒋\u{FFFD}")); - } - - #[test] - fn test_push_bytes() { - let mut s = String::from_str("ABC"); - unsafe { - let mv = s.as_mut_vec(); - mv.push_all(&[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_push() { - let mut data = String::from_str("ประเทศไทย中"); - 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_str("ประเทศไทย中华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_str_truncate() { - let mut s = String::from_str("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_str("12345"); - let p = s.as_ptr(); - s.truncate(3); - s.push_str("6"); - let p_ = s.as_ptr(); - assert_eq!(p_, p); - } - - #[test] - #[should_panic] - fn test_str_truncate_invalid_len() { - let mut s = String::from_str("12345"); - s.truncate(6); - } - - #[test] - #[should_panic] - fn test_str_truncate_split_codepoint() { - let mut s = String::from_str("\u{FC}"); // ü - s.truncate(1); - } - - #[test] - fn test_str_clear() { - let mut s = String::from_str("12345"); - s.clear(); - assert_eq!(s.len(), 0); - assert_eq!(s, ""); - } - - #[test] - fn test_str_add() { - let a = String::from_str("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 = 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].into_iter()); - assert_eq!(s, d); - } - - #[bench] - fn bench_with_capacity(b: &mut Bencher) { - b.iter(|| { - String::with_capacity(100) - }); - } - - #[bench] - fn bench_push_str(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - b.iter(|| { - let mut r = String::new(); - r.push_str(s); - }); - } - - const REPETITIONS: u64 = 10_000; - - #[bench] - fn bench_push_str_one_byte(b: &mut Bencher) { - b.bytes = REPETITIONS; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push_str("a") - } - }); - } - - #[bench] - fn bench_push_char_one_byte(b: &mut Bencher) { - b.bytes = REPETITIONS; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push('a') - } - }); - } - - #[bench] - fn bench_push_char_two_bytes(b: &mut Bencher) { - b.bytes = REPETITIONS * 2; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push('â') - } - }); - } - - #[bench] - fn from_utf8_lossy_100_ascii(b: &mut Bencher) { - let s = b"Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "; - - assert_eq!(100, s.len()); - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); - } - - #[bench] - fn from_utf8_lossy_100_multibyte(b: &mut Bencher) { - let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); - assert_eq!(100, s.len()); - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); - } - - #[bench] - fn from_utf8_lossy_invalid(b: &mut Bencher) { - let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); - } - - #[bench] - fn from_utf8_lossy_100_invalid(b: &mut Bencher) { - let s = repeat(0xf5).take(100).collect::>(); - b.iter(|| { - let _ = String::from_utf8_lossy(&s); - }); - } - - #[bench] - fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { - let s = "Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "; - // ensure our operation produces an exact-size string before we benchmark it - let mut r = String::with_capacity(s.len()); - r.push_str(s); - assert_eq!(r.len(), r.capacity()); - b.iter(|| { - let mut r = String::with_capacity(s.len()); - r.push_str(s); - r.shrink_to_fit(); - r - }); - } -} diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 82d68caeb3642..22da0a191ca24 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1951,991 +1951,3 @@ impl Drop for PartialVecZeroSized { } } } - -#[cfg(test)] -mod tests { - use prelude::*; - use core::mem::size_of; - use core::iter::repeat; - use test::Bencher; - use super::as_vec; - - struct DropCounter<'a> { - count: &'a mut u32 - } - - #[unsafe_destructor] - impl<'a> Drop for DropCounter<'a> { - fn drop(&mut self) { - *self.count += 1; - } - } - - #[test] - fn test_as_vec() { - let xs = [1u8, 2u8, 3u8]; - assert_eq!(&**as_vec(&xs), xs); - } - - #[test] - fn test_as_vec_dtor() { - let (mut count_x, mut count_y) = (0, 0); - { - let xs = &[DropCounter { count: &mut count_x }, DropCounter { count: &mut count_y }]; - assert_eq!(as_vec(xs).len(), 2); - } - assert_eq!(count_x, 1); - assert_eq!(count_y, 1); - } - - #[test] - fn test_small_vec_struct() { - assert!(size_of::>() == size_of::() * 3); - } - - #[test] - fn test_double_drop() { - struct TwoVec { - x: Vec, - y: Vec - } - - 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); - } - - #[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 = 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> = vec!(box 1, box 2, box 3); - let two: Vec> = 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 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_unsafe_ptrs() { - unsafe { - // Test on-stack copy-from-buf. - let a = [1, 2, 3]; - let ptr = a.as_ptr(); - let b = Vec::from_raw_buf(ptr, 3); - assert_eq!(b, [1, 2, 3]); - - // Test on-heap copy-from-buf. - let c = vec![1, 2, 3, 4, 5]; - let ptr = c.as_ptr(); - let d = Vec::from_raw_buf(ptr, 5); - assert_eq!(d, [1, 2, 3, 4, 5]); - } - } - - #[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[-1..]; - } - - #[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[-1..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::::new(); - vec.swap_remove(0); - } - - #[test] - fn test_move_iter_unwrap() { - let mut vec = Vec::with_capacity(7); - vec.push(1); - vec.push(2); - let ptr = vec.as_ptr(); - vec = vec.into_iter().into_inner(); - assert_eq!(vec.as_ptr(), ptr); - assert_eq!(vec.capacity(), 7); - assert_eq!(vec.len(), 0); - } - - #[test] - #[should_panic] - fn test_map_in_place_incompatible_types_fail() { - let v = vec![0, 1, 2]; - v.map_in_place(|_| ()); - } - - #[test] - fn test_map_in_place() { - let v = vec![0, 1, 2]; - assert_eq!(v.map_in_place(|i: u32| i as i32 - 1), [-1, 0, 1]); - } - - #[test] - fn test_map_in_place_zero_sized() { - let v = vec![(), ()]; - #[derive(PartialEq, Debug)] - struct ZeroSized; - assert_eq!(v.map_in_place(|_| ZeroSized), [ZeroSized, ZeroSized]); - } - - #[test] - fn test_map_in_place_zero_drop_count() { - use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; - - #[derive(Clone, PartialEq, Debug)] - struct Nothing; - impl Drop for Nothing { fn drop(&mut self) { } } - - #[derive(Clone, PartialEq, Debug)] - struct ZeroSized; - impl Drop for ZeroSized { - fn drop(&mut self) { - DROP_COUNTER.fetch_add(1, Ordering::Relaxed); - } - } - const NUM_ELEMENTS: usize = 2; - static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; - - let v = repeat(Nothing).take(NUM_ELEMENTS).collect::>(); - - DROP_COUNTER.store(0, Ordering::Relaxed); - - let v = v.map_in_place(|_| ZeroSized); - assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), 0); - drop(v); - assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), NUM_ELEMENTS); - } - - #[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] - 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]); - } - - #[bench] - fn bench_new(b: &mut Bencher) { - b.iter(|| { - let v: Vec = Vec::new(); - assert_eq!(v.len(), 0); - assert_eq!(v.capacity(), 0); - }) - } - - fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| { - let v: Vec = Vec::with_capacity(src_len); - assert_eq!(v.len(), 0); - assert_eq!(v.capacity(), src_len); - }) - } - - #[bench] - fn bench_with_capacity_0000(b: &mut Bencher) { - do_bench_with_capacity(b, 0) - } - - #[bench] - fn bench_with_capacity_0010(b: &mut Bencher) { - do_bench_with_capacity(b, 10) - } - - #[bench] - fn bench_with_capacity_0100(b: &mut Bencher) { - do_bench_with_capacity(b, 100) - } - - #[bench] - fn bench_with_capacity_1000(b: &mut Bencher) { - do_bench_with_capacity(b, 1000) - } - - fn do_bench_from_fn(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| { - let dst = (0..src_len).collect::>(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }) - } - - #[bench] - fn bench_from_fn_0000(b: &mut Bencher) { - do_bench_from_fn(b, 0) - } - - #[bench] - fn bench_from_fn_0010(b: &mut Bencher) { - do_bench_from_fn(b, 10) - } - - #[bench] - fn bench_from_fn_0100(b: &mut Bencher) { - do_bench_from_fn(b, 100) - } - - #[bench] - fn bench_from_fn_1000(b: &mut Bencher) { - do_bench_from_fn(b, 1000) - } - - fn do_bench_from_elem(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| { - let dst: Vec = repeat(5).take(src_len).collect(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().all(|x| *x == 5)); - }) - } - - #[bench] - fn bench_from_elem_0000(b: &mut Bencher) { - do_bench_from_elem(b, 0) - } - - #[bench] - fn bench_from_elem_0010(b: &mut Bencher) { - do_bench_from_elem(b, 10) - } - - #[bench] - fn bench_from_elem_0100(b: &mut Bencher) { - do_bench_from_elem(b, 100) - } - - #[bench] - fn bench_from_elem_1000(b: &mut Bencher) { - do_bench_from_elem(b, 1000) - } - - fn do_bench_from_slice(b: &mut Bencher, src_len: usize) { - let src: Vec<_> = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let dst = src.clone()[..].to_vec(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_from_slice_0000(b: &mut Bencher) { - do_bench_from_slice(b, 0) - } - - #[bench] - fn bench_from_slice_0010(b: &mut Bencher) { - do_bench_from_slice(b, 10) - } - - #[bench] - fn bench_from_slice_0100(b: &mut Bencher) { - do_bench_from_slice(b, 100) - } - - #[bench] - fn bench_from_slice_1000(b: &mut Bencher) { - do_bench_from_slice(b, 1000) - } - - fn do_bench_from_iter(b: &mut Bencher, src_len: usize) { - let src: Vec<_> = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let dst: Vec<_> = FromIterator::from_iter(src.clone().into_iter()); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_from_iter_0000(b: &mut Bencher) { - do_bench_from_iter(b, 0) - } - - #[bench] - fn bench_from_iter_0010(b: &mut Bencher) { - do_bench_from_iter(b, 10) - } - - #[bench] - fn bench_from_iter_0100(b: &mut Bencher) { - do_bench_from_iter(b, 100) - } - - #[bench] - fn bench_from_iter_1000(b: &mut Bencher) { - do_bench_from_iter(b, 1000) - } - - fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..dst_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let mut dst = dst.clone(); - dst.extend(src.clone().into_iter()); - assert_eq!(dst.len(), dst_len + src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_extend_0000_0000(b: &mut Bencher) { - do_bench_extend(b, 0, 0) - } - - #[bench] - fn bench_extend_0000_0010(b: &mut Bencher) { - do_bench_extend(b, 0, 10) - } - - #[bench] - fn bench_extend_0000_0100(b: &mut Bencher) { - do_bench_extend(b, 0, 100) - } - - #[bench] - fn bench_extend_0000_1000(b: &mut Bencher) { - do_bench_extend(b, 0, 1000) - } - - #[bench] - fn bench_extend_0010_0010(b: &mut Bencher) { - do_bench_extend(b, 10, 10) - } - - #[bench] - fn bench_extend_0100_0100(b: &mut Bencher) { - do_bench_extend(b, 100, 100) - } - - #[bench] - fn bench_extend_1000_1000(b: &mut Bencher) { - do_bench_extend(b, 1000, 1000) - } - - fn do_bench_push_all(b: &mut Bencher, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..dst_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let mut dst = dst.clone(); - dst.push_all(&src); - assert_eq!(dst.len(), dst_len + src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_push_all_0000_0000(b: &mut Bencher) { - do_bench_push_all(b, 0, 0) - } - - #[bench] - fn bench_push_all_0000_0010(b: &mut Bencher) { - do_bench_push_all(b, 0, 10) - } - - #[bench] - fn bench_push_all_0000_0100(b: &mut Bencher) { - do_bench_push_all(b, 0, 100) - } - - #[bench] - fn bench_push_all_0000_1000(b: &mut Bencher) { - do_bench_push_all(b, 0, 1000) - } - - #[bench] - fn bench_push_all_0010_0010(b: &mut Bencher) { - do_bench_push_all(b, 10, 10) - } - - #[bench] - fn bench_push_all_0100_0100(b: &mut Bencher) { - do_bench_push_all(b, 100, 100) - } - - #[bench] - fn bench_push_all_1000_1000(b: &mut Bencher) { - do_bench_push_all(b, 1000, 1000) - } - - fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..dst_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let mut dst = dst.clone(); - dst.extend(src.clone().into_iter()); - assert_eq!(dst.len(), dst_len + src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_push_all_move_0000_0000(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 0) - } - - #[bench] - fn bench_push_all_move_0000_0010(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 10) - } - - #[bench] - fn bench_push_all_move_0000_0100(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 100) - } - - #[bench] - fn bench_push_all_move_0000_1000(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 1000) - } - - #[bench] - fn bench_push_all_move_0010_0010(b: &mut Bencher) { - do_bench_push_all_move(b, 10, 10) - } - - #[bench] - fn bench_push_all_move_0100_0100(b: &mut Bencher) { - do_bench_push_all_move(b, 100, 100) - } - - #[bench] - fn bench_push_all_move_1000_1000(b: &mut Bencher) { - do_bench_push_all_move(b, 1000, 1000) - } - - fn do_bench_clone(b: &mut Bencher, src_len: usize) { - let src: Vec = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let dst = src.clone(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_clone_0000(b: &mut Bencher) { - do_bench_clone(b, 0) - } - - #[bench] - fn bench_clone_0010(b: &mut Bencher) { - do_bench_clone(b, 10) - } - - #[bench] - fn bench_clone_0100(b: &mut Bencher) { - do_bench_clone(b, 100) - } - - #[bench] - fn bench_clone_1000(b: &mut Bencher) { - do_bench_clone(b, 1000) - } - - fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..src_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = (times * src_len) as u64; - - b.iter(|| { - let mut dst = dst.clone(); - - for _ in 0..times { - dst.clone_from(&src); - - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x)); - } - }); - } - - #[bench] - fn bench_clone_from_01_0000_0000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 0) - } - - #[bench] - fn bench_clone_from_01_0000_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 10) - } - - #[bench] - fn bench_clone_from_01_0000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 100) - } - - #[bench] - fn bench_clone_from_01_0000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 1000) - } - - #[bench] - fn bench_clone_from_01_0010_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 10) - } - - #[bench] - fn bench_clone_from_01_0100_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 100) - } - - #[bench] - fn bench_clone_from_01_1000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 1000, 1000) - } - - #[bench] - fn bench_clone_from_01_0010_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 100) - } - - #[bench] - fn bench_clone_from_01_0100_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 1000) - } - - #[bench] - fn bench_clone_from_01_0010_0000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 0) - } - - #[bench] - fn bench_clone_from_01_0100_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 10) - } - - #[bench] - fn bench_clone_from_01_1000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 1000, 100) - } - - #[bench] - fn bench_clone_from_10_0000_0000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 0) - } - - #[bench] - fn bench_clone_from_10_0000_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 10) - } - - #[bench] - fn bench_clone_from_10_0000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 100) - } - - #[bench] - fn bench_clone_from_10_0000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 1000) - } - - #[bench] - fn bench_clone_from_10_0010_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 10) - } - - #[bench] - fn bench_clone_from_10_0100_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 100) - } - - #[bench] - fn bench_clone_from_10_1000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 1000, 1000) - } - - #[bench] - fn bench_clone_from_10_0010_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 100) - } - - #[bench] - fn bench_clone_from_10_0100_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 1000) - } - - #[bench] - fn bench_clone_from_10_0010_0000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 0) - } - - #[bench] - fn bench_clone_from_10_0100_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 10) - } - - #[bench] - fn bench_clone_from_10_1000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 1000, 100) - } -} diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 65e44703df108..700ee059a7fa5 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -1768,1121 +1768,3 @@ impl fmt::Debug for VecDeque { write!(f, "]") } } - -#[cfg(test)] -mod tests { - use self::Taggy::*; - use self::Taggypar::*; - use prelude::*; - use core::iter; - use std::fmt::Debug; - use std::hash::{self, SipHasher}; - use test::Bencher; - use test; - - use super::VecDeque; - - #[test] - #[allow(deprecated)] - 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); - debug!("{}", d[0]); - debug!("{}", d[1]); - debug!("{}", d[2]); - debug!("{}", d[3]); - 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(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]; - } - - #[bench] - fn bench_new(b: &mut test::Bencher) { - b.iter(|| { - let ring: VecDeque = VecDeque::new(); - test::black_box(ring); - }) - } - - #[bench] - fn bench_push_back_100(b: &mut test::Bencher) { - let mut deq = VecDeque::with_capacity(101); - b.iter(|| { - for i in 0..100 { - deq.push_back(i); - } - deq.head = 0; - deq.tail = 0; - }) - } - - #[bench] - fn bench_push_front_100(b: &mut test::Bencher) { - let mut deq = VecDeque::with_capacity(101); - b.iter(|| { - for i in 0..100 { - deq.push_front(i); - } - deq.head = 0; - deq.tail = 0; - }) - } - - #[bench] - fn bench_pop_back_100(b: &mut test::Bencher) { - let mut deq= VecDeque::::with_capacity(101); - - b.iter(|| { - deq.head = 100; - deq.tail = 0; - while !deq.is_empty() { - test::black_box(deq.pop_back()); - } - }) - } - - #[bench] - fn bench_pop_front_100(b: &mut test::Bencher) { - let mut deq = VecDeque::::with_capacity(101); - - b.iter(|| { - deq.head = 100; - deq.tail = 0; - while !deq.is_empty() { - test::black_box(deq.pop_front()); - } - }) - } - - #[bench] - fn bench_grow_1025(b: &mut test::Bencher) { - b.iter(|| { - let mut deq = VecDeque::new(); - for i in 0..1025 { - deq.push_front(i); - } - test::black_box(deq); - }) - } - - #[bench] - fn bench_iter_1000(b: &mut test::Bencher) { - let ring: VecDeque<_> = (0..1000).collect(); - - b.iter(|| { - let mut sum = 0; - for &i in &ring { - sum += i; - } - test::black_box(sum); - }) - } - - #[bench] - fn bench_mut_iter_1000(b: &mut test::Bencher) { - let mut ring: VecDeque<_> = (0..1000).collect(); - - b.iter(|| { - let mut sum = 0; - for i in &mut ring { - sum += *i; - } - test::black_box(sum); - }) - } - - #[derive(Clone, PartialEq, Debug)] - enum Taggy { - One(i32), - Two(i32, i32), - Three(i32, i32, i32), - } - - #[derive(Clone, PartialEq, Debug)] - enum Taggypar { - 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::(5, 72, 64, 175); - } - - #[test] - fn test_param_taggy() { - test_parameterized::(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); - } - - #[test] - fn test_param_taggypar() { - test_parameterized::>(Onepar::(1), - Twopar::(1, 2), - Threepar::(1, 2, 3), - Twopar::(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::(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::>(), [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::>(), 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::>(), 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::>(), 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::>(), 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().cloned().collect::>(), - 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 = 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::>(), 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::>(), 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 = 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::>(), [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::>(), [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() { - use core::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 = iter::count(0, 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_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::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); - } - - #[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_swap_front_back_remove() { - fn test(back: bool) { - // This test checks that every single combination of tail position and length is tested. - // Capacity 15 should be large enough to cover every case. - let mut tester = VecDeque::with_capacity(15); - let usable_cap = tester.capacity(); - let final_len = usable_cap / 2; - - for len in 0..final_len { - let expected = if back { - (0..len).collect() - } else { - (0..len).rev().collect() - }; - for tail_pos in 0..usable_cap { - tester.tail = tail_pos; - tester.head = tail_pos; - if back { - for i in 0..len * 2 { - tester.push_front(i); - } - for i in 0..len { - assert_eq!(tester.swap_back_remove(i), Some(len * 2 - 1 - i)); - } - } else { - for i in 0..len * 2 { - tester.push_back(i); - } - for i in 0..len { - let idx = tester.len() - 1 - i; - assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i)); - } - } - assert!(tester.tail < tester.cap); - assert!(tester.head < tester.cap); - assert_eq!(tester, expected); - } - } - } - test(true); - test(false); - } - - #[test] - fn test_insert() { - // This test checks that every single combination of tail position, length, and - // insertion position is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - - - // len is the length *after* insertion - for len in 1..cap { - // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); - for tail_pos in 0..cap { - for to_insert in 0..len { - tester.tail = tail_pos; - tester.head = tail_pos; - for i in 0..len { - if i != to_insert { - tester.push_back(i); - } - } - tester.insert(to_insert, to_insert); - assert!(tester.tail < tester.cap); - assert!(tester.head < tester.cap); - assert_eq!(tester, expected); - } - } - } - } - - #[test] - fn test_remove() { - // This test checks that every single combination of tail position, length, and - // removal position is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - - // len is the length *after* removal - for len in 0..cap - 1 { - // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); - for tail_pos in 0..cap { - for to_remove in 0..len + 1 { - tester.tail = tail_pos; - tester.head = tail_pos; - for i in 0..len { - if i == to_remove { - tester.push_back(1234); - } - tester.push_back(i); - } - if to_remove == len { - tester.push_back(1234); - } - tester.remove(to_remove); - assert!(tester.tail < tester.cap); - assert!(tester.head < tester.cap); - assert_eq!(tester, expected); - } - } - } - } - - #[test] - fn test_shrink_to_fit() { - // This test checks that every single combination of head and tail position, - // is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - tester.reserve(63); - let max_cap = tester.capacity(); - - for len in 0..cap + 1 { - // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); - for tail_pos in 0..max_cap + 1 { - tester.tail = tail_pos; - tester.head = tail_pos; - tester.reserve(63); - for i in 0..len { - tester.push_back(i); - } - tester.shrink_to_fit(); - assert!(tester.capacity() <= cap); - assert!(tester.tail < tester.cap); - assert!(tester.head < tester.cap); - assert_eq!(tester, expected); - } - } - } - - #[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 = 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 = 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_split_off() { - // This test checks that every single combination of tail position, length, and - // split position is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - - // len is the length *before* splitting - for len in 0..cap { - // index to split at - for at in 0..len + 1 { - // 0, 1, 2, .., at - 1 (may be empty) - let expected_self = iter::count(0, 1).take(at).collect(); - // at, at + 1, .., len - 1 (may be empty) - let expected_other = iter::count(at, 1).take(len - at).collect(); - - for tail_pos in 0..cap { - tester.tail = tail_pos; - tester.head = tail_pos; - for i in 0..len { - tester.push_back(i); - } - let result = tester.split_off(at); - assert!(tester.tail < tester.cap); - assert!(tester.head < tester.cap); - assert!(result.tail < result.cap); - assert!(result.head < result.cap); - assert_eq!(tester, expected_self); - assert_eq!(result, expected_other); - } - } - } - } - - #[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::>(), [1, 2, 3, 4, 5, 6]); - assert_eq!(b.iter().cloned().collect::>(), []); - - // append nothing to something - a.append(&mut b); - assert_eq!(a.iter().cloned().collect::>(), [1, 2, 3, 4, 5, 6]); - assert_eq!(b.iter().cloned().collect::>(), []); - - // append something to nothing - b.append(&mut a); - assert_eq!(b.iter().cloned().collect::>(), [1, 2, 3, 4, 5, 6]); - assert_eq!(a.iter().cloned().collect::>(), []); - } -} diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 431c8d5df8c0a..6e67d8763273d 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -1004,510 +1004,3 @@ impl Iterator for IntoIter { impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option<(usize, V)> { self.iter.next_back() } } - -#[cfg(test)] -mod test_map { - use prelude::*; - use core::hash::{hash, SipHasher}; - - use super::VecMap; - use super::Entry::{Occupied, Vacant}; - - #[test] - fn test_get_mut() { - let mut m = VecMap::new(); - assert!(m.insert(1, 12).is_none()); - assert!(m.insert(2, 8).is_none()); - assert!(m.insert(5, 14).is_none()); - let new = 100; - match m.get_mut(&5) { - None => panic!(), Some(x) => *x = new - } - assert_eq!(m.get(&5), Some(&new)); - } - - #[test] - fn test_len() { - let mut map = VecMap::new(); - assert_eq!(map.len(), 0); - assert!(map.is_empty()); - assert!(map.insert(5, 20).is_none()); - assert_eq!(map.len(), 1); - assert!(!map.is_empty()); - assert!(map.insert(11, 12).is_none()); - assert_eq!(map.len(), 2); - assert!(!map.is_empty()); - assert!(map.insert(14, 22).is_none()); - assert_eq!(map.len(), 3); - assert!(!map.is_empty()); - } - - #[test] - fn test_clear() { - let mut map = VecMap::new(); - assert!(map.insert(5, 20).is_none()); - assert!(map.insert(11, 12).is_none()); - assert!(map.insert(14, 22).is_none()); - map.clear(); - assert!(map.is_empty()); - assert!(map.get(&5).is_none()); - assert!(map.get(&11).is_none()); - assert!(map.get(&14).is_none()); - } - - #[test] - fn test_insert() { - let mut m = VecMap::new(); - assert_eq!(m.insert(1, 2), None); - assert_eq!(m.insert(1, 3), Some(2)); - assert_eq!(m.insert(1, 4), Some(3)); - } - - #[test] - fn test_remove() { - let mut m = VecMap::new(); - m.insert(1, 2); - assert_eq!(m.remove(&1), Some(2)); - assert_eq!(m.remove(&1), None); - } - - #[test] - fn test_keys() { - let mut map = VecMap::new(); - map.insert(1, 'a'); - map.insert(2, 'b'); - map.insert(3, 'c'); - let keys: Vec<_> = map.keys().collect(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let mut map = VecMap::new(); - map.insert(1, 'a'); - map.insert(2, 'b'); - map.insert(3, 'c'); - let values: Vec<_> = map.values().cloned().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - let mut it = m.iter(); - assert_eq!(it.size_hint(), (0, Some(11))); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.size_hint(), (0, Some(10))); - assert_eq!(it.next().unwrap(), (1, &2)); - assert_eq!(it.size_hint(), (0, Some(9))); - assert_eq!(it.next().unwrap(), (3, &5)); - assert_eq!(it.size_hint(), (0, Some(7))); - assert_eq!(it.next().unwrap(), (6, &10)); - assert_eq!(it.size_hint(), (0, Some(4))); - assert_eq!(it.next().unwrap(), (10, &11)); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - - #[test] - fn test_iterator_size_hints() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - assert_eq!(m.iter().size_hint(), (0, Some(11))); - assert_eq!(m.iter().rev().size_hint(), (0, Some(11))); - assert_eq!(m.iter_mut().size_hint(), (0, Some(11))); - assert_eq!(m.iter_mut().rev().size_hint(), (0, Some(11))); - } - - #[test] - fn test_mut_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - for (k, v) in &mut m { - *v += k as isize; - } - - let mut it = m.iter(); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.next().unwrap(), (1, &3)); - assert_eq!(it.next().unwrap(), (3, &8)); - assert_eq!(it.next().unwrap(), (6, &16)); - assert_eq!(it.next().unwrap(), (10, &21)); - assert!(it.next().is_none()); - } - - #[test] - fn test_rev_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - let mut it = m.iter().rev(); - assert_eq!(it.next().unwrap(), (10, &11)); - assert_eq!(it.next().unwrap(), (6, &10)); - assert_eq!(it.next().unwrap(), (3, &5)); - assert_eq!(it.next().unwrap(), (1, &2)); - assert_eq!(it.next().unwrap(), (0, &1)); - assert!(it.next().is_none()); - } - - #[test] - fn test_mut_rev_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - for (k, v) in m.iter_mut().rev() { - *v += k as isize; - } - - let mut it = m.iter(); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.next().unwrap(), (1, &3)); - assert_eq!(it.next().unwrap(), (3, &8)); - assert_eq!(it.next().unwrap(), (6, &16)); - assert_eq!(it.next().unwrap(), (10, &21)); - assert!(it.next().is_none()); - } - - #[test] - fn test_move_iter() { - let mut m: VecMap> = VecMap::new(); - m.insert(1, box 2); - let mut called = false; - for (k, v) in m { - assert!(!called); - called = true; - assert_eq!(k, 1); - assert_eq!(v, box 2); - } - assert!(called); - } - - #[test] - fn test_drain_iterator() { - let mut map = VecMap::new(); - map.insert(1, "a"); - map.insert(3, "c"); - map.insert(2, "b"); - - let vec: Vec<_> = map.drain().collect(); - - assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); - assert_eq!(map.len(), 0); - } - - #[test] - fn test_append() { - let mut a = VecMap::new(); - a.insert(1, "a"); - a.insert(2, "b"); - a.insert(3, "c"); - - let mut b = VecMap::new(); - b.insert(3, "d"); // Overwrite element from a - b.insert(4, "e"); - b.insert(5, "f"); - - a.append(&mut b); - - assert_eq!(a.len(), 5); - assert_eq!(b.len(), 0); - // Capacity shouldn't change for possible reuse - assert!(b.capacity() >= 4); - - assert_eq!(a[1], "a"); - assert_eq!(a[2], "b"); - assert_eq!(a[3], "d"); - assert_eq!(a[4], "e"); - assert_eq!(a[5], "f"); - } - - #[test] - fn test_split_off() { - // Split within the key range - let mut a = VecMap::new(); - a.insert(1, "a"); - a.insert(2, "b"); - a.insert(3, "c"); - a.insert(4, "d"); - - let b = a.split_off(3); - - assert_eq!(a.len(), 2); - assert_eq!(b.len(), 2); - - assert_eq!(a[1], "a"); - assert_eq!(a[2], "b"); - - assert_eq!(b[3], "c"); - assert_eq!(b[4], "d"); - - // Split at 0 - a.clear(); - a.insert(1, "a"); - a.insert(2, "b"); - a.insert(3, "c"); - a.insert(4, "d"); - - let b = a.split_off(0); - - assert_eq!(a.len(), 0); - assert_eq!(b.len(), 4); - assert_eq!(b[1], "a"); - assert_eq!(b[2], "b"); - assert_eq!(b[3], "c"); - assert_eq!(b[4], "d"); - - // Split behind max_key - a.clear(); - a.insert(1, "a"); - a.insert(2, "b"); - a.insert(3, "c"); - a.insert(4, "d"); - - let b = a.split_off(5); - - assert_eq!(a.len(), 4); - assert_eq!(b.len(), 0); - assert_eq!(a[1], "a"); - assert_eq!(a[2], "b"); - assert_eq!(a[3], "c"); - assert_eq!(a[4], "d"); - } - - #[test] - fn test_show() { - let mut map = VecMap::new(); - let empty = VecMap::::new(); - - map.insert(1, 2); - map.insert(3, 4); - - let map_str = format!("{:?}", map); - assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); - assert_eq!(format!("{:?}", empty), "{}"); - } - - #[test] - fn test_clone() { - let mut a = VecMap::new(); - - a.insert(1, 'x'); - a.insert(4, 'y'); - a.insert(6, 'z'); - - assert!(a.clone() == a); - } - - #[test] - fn test_eq() { - let mut a = VecMap::new(); - let mut b = VecMap::new(); - - assert!(a == b); - assert!(a.insert(0, 5).is_none()); - assert!(a != b); - assert!(b.insert(0, 4).is_none()); - assert!(a != b); - assert!(a.insert(5, 19).is_none()); - assert!(a != b); - assert!(!b.insert(0, 5).is_none()); - assert!(a != b); - assert!(b.insert(5, 19).is_none()); - assert!(a == b); - - a = VecMap::new(); - b = VecMap::with_capacity(1); - assert!(a == b); - } - - #[test] - fn test_lt() { - let mut a = VecMap::new(); - let mut b = VecMap::new(); - - assert!(!(a < b) && !(b < a)); - assert!(b.insert(2, 5).is_none()); - assert!(a < b); - assert!(a.insert(2, 7).is_none()); - assert!(!(a < b) && b < a); - assert!(b.insert(1, 0).is_none()); - assert!(b < a); - assert!(a.insert(0, 6).is_none()); - assert!(a < b); - assert!(a.insert(6, 2).is_none()); - assert!(a < b && !(b < a)); - } - - #[test] - fn test_ord() { - let mut a = VecMap::new(); - let mut b = VecMap::new(); - - assert!(a <= b && a >= b); - assert!(a.insert(1, 1).is_none()); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - assert!(b.insert(2, 2).is_none()); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } - - #[test] - fn test_hash() { - let mut x = VecMap::new(); - let mut y = VecMap::new(); - - assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); - x.insert(1, 'a'); - x.insert(2, 'b'); - x.insert(3, 'c'); - - y.insert(3, 'c'); - y.insert(2, 'b'); - y.insert(1, 'a'); - - assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); - - x.insert(1000, 'd'); - x.remove(&1000); - - assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); - } - - #[test] - fn test_from_iter() { - let xs = vec![(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]; - - let map: VecMap<_> = xs.iter().cloned().collect(); - - for &(k, v) in &xs { - assert_eq!(map.get(&k), Some(&v)); - } - } - - #[test] - fn test_index() { - let mut map = VecMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - assert_eq!(map[3], 4); - } - - #[test] - #[should_panic] - fn test_index_nonexistent() { - let mut map = VecMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - map[4]; - } - - #[test] - fn test_entry(){ - let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: VecMap<_> = 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); - } -} - -#[cfg(test)] -mod bench { - use super::VecMap; - - map_insert_rand_bench!{insert_rand_100, 100, VecMap} - map_insert_rand_bench!{insert_rand_10_000, 10_000, VecMap} - - map_insert_seq_bench!{insert_seq_100, 100, VecMap} - map_insert_seq_bench!{insert_seq_10_000, 10_000, VecMap} - - map_find_rand_bench!{find_rand_100, 100, VecMap} - map_find_rand_bench!{find_rand_10_000, 10_000, VecMap} - - map_find_seq_bench!{find_seq_100, 100, VecMap} - map_find_seq_bench!{find_seq_10_000, 10_000, VecMap} -} diff --git a/src/libcollections/bench.rs b/src/libcollectionstest/bench.rs similarity index 99% rename from src/libcollections/bench.rs rename to src/libcollectionstest/bench.rs index 107f6031c1156..2396a577589f2 100644 --- a/src/libcollections/bench.rs +++ b/src/libcollectionstest/bench.rs @@ -66,11 +66,11 @@ macro_rules! map_find_rand_bench { ($name: ident, $n: expr, $map: ident) => ( #[bench] pub fn $name(b: &mut ::test::Bencher) { - use std::rand; use std::iter::IteratorExt; use std::rand::Rng; + use std::rand; + use std::vec::Vec; use test::black_box; - use vec::Vec; let mut map = $map::new(); let n: usize = $n; diff --git a/src/libcollectionstest/binary_heap.rs b/src/libcollectionstest/binary_heap.rs new file mode 100644 index 0000000000000..47a366bb1e2e0 --- /dev/null +++ b/src/libcollectionstest/binary_heap.rs @@ -0,0 +1,219 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BinaryHeap; + +#[test] +fn test_iterator() { + let data = vec![5, 9, 3]; + let iterout = [9, 5, 3]; + let heap = BinaryHeap::from_vec(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_vec(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_vec(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_vec(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_vec(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_vec(data); + while !heap.is_empty() { + assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); + assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); + } +} + +#[test] +fn test_push() { + let mut heap = BinaryHeap::from_vec(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::>::from_vec(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] +fn test_push_pop() { + let mut heap = BinaryHeap::from_vec(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] +fn test_replace() { + let mut heap = BinaryHeap::from_vec(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) { + let heap = BinaryHeap::from_vec(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::::new(); + assert!(heap.pop().is_none()); +} + +#[test] +fn test_empty_peek() { + let empty = BinaryHeap::::new(); + assert!(empty.peek().is_none()); +} + +#[test] +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()); +} diff --git a/src/libcollectionstest/bit/mod.rs b/src/libcollectionstest/bit/mod.rs new file mode 100644 index 0000000000000..8e06524f2e5ae --- /dev/null +++ b/src/libcollectionstest/bit/mod.rs @@ -0,0 +1,12 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod set; +mod vec; diff --git a/src/libcollectionstest/bit/set.rs b/src/libcollectionstest/bit/set.rs new file mode 100644 index 0000000000000..4b4995d5fa7d9 --- /dev/null +++ b/src/libcollectionstest/bit/set.rs @@ -0,0 +1,441 @@ +// 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 or the MIT license +// , 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::collections::{BitSet, BitVec}; +use std::iter::range_step; + +#[test] +fn test_bit_set_show() { + let mut s = BitSet::new(); + s.insert(1); + s.insert(10); + s.insert(50); + s.insert(2); + assert_eq!("{1, 2, 10, 50}", format!("{:?}", s)); +} + +#[test] +fn test_bit_set_from_usizes() { + let usizes = vec![0, 2, 2, 3]; + let a: BitSet = usizes.into_iter().collect(); + let mut b = BitSet::new(); + b.insert(0); + b.insert(2); + b.insert(3); + assert_eq!(a, b); +} + +#[test] +fn test_bit_set_iterator() { + let usizes = vec![0, 2, 2, 3]; + let bit_vec: BitSet = usizes.into_iter().collect(); + + let idxs: Vec<_> = bit_vec.iter().collect(); + assert_eq!(idxs, [0, 2, 3]); + + let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect(); + let real: Vec<_> = range_step(0, 10000, 2).collect(); + + let idxs: Vec<_> = long.iter().collect(); + assert_eq!(idxs, real); +} + +#[test] +fn test_bit_set_frombit_vec_init() { + let bools = [true, false]; + let lengths = [10, 64, 100]; + for &b in &bools { + for &l in &lengths { + let bitset = BitSet::from_bit_vec(BitVec::from_elem(l, b)); + assert_eq!(bitset.contains(&1), b); + assert_eq!(bitset.contains(&(l-1)), b); + assert!(!bitset.contains(&l)); + } + } +} + +#[test] +fn test_bit_vec_masking() { + let b = BitVec::from_elem(140, true); + let mut bs = BitSet::from_bit_vec(b); + assert!(bs.contains(&139)); + assert!(!bs.contains(&140)); + assert!(bs.insert(150)); + assert!(!bs.contains(&140)); + assert!(!bs.contains(&149)); + assert!(bs.contains(&150)); + assert!(!bs.contains(&151)); +} + +#[test] +fn test_bit_set_basic() { + let mut b = BitSet::new(); + assert!(b.insert(3)); + assert!(!b.insert(3)); + assert!(b.contains(&3)); + assert!(b.insert(4)); + assert!(!b.insert(4)); + assert!(b.contains(&3)); + assert!(b.insert(400)); + assert!(!b.insert(400)); + assert!(b.contains(&400)); + assert_eq!(b.len(), 3); +} + +#[test] +fn test_bit_set_intersection() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + + assert!(a.insert(11)); + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(77)); + assert!(a.insert(103)); + assert!(a.insert(5)); + + assert!(b.insert(2)); + assert!(b.insert(11)); + assert!(b.insert(77)); + assert!(b.insert(5)); + assert!(b.insert(3)); + + let expected = [3, 5, 11, 77]; + let actual: Vec<_> = a.intersection(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_difference() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(200)); + assert!(a.insert(500)); + + assert!(b.insert(3)); + assert!(b.insert(200)); + + let expected = [1, 5, 500]; + let actual: Vec<_> = a.difference(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_symmetric_difference() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + + assert!(b.insert(3)); + assert!(b.insert(9)); + assert!(b.insert(14)); + assert!(b.insert(220)); + + let expected = [1, 5, 11, 14, 220]; + let actual: Vec<_> = a.symmetric_difference(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_union() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + assert!(a.insert(160)); + assert!(a.insert(19)); + assert!(a.insert(24)); + assert!(a.insert(200)); + + assert!(b.insert(1)); + assert!(b.insert(5)); + assert!(b.insert(9)); + assert!(b.insert(13)); + assert!(b.insert(19)); + + let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160, 200]; + let actual: Vec<_> = a.union(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_subset() { + let mut set1 = BitSet::new(); + let mut set2 = BitSet::new(); + + assert!(set1.is_subset(&set2)); // {} {} + set2.insert(100); + assert!(set1.is_subset(&set2)); // {} { 1 } + set2.insert(200); + assert!(set1.is_subset(&set2)); // {} { 1, 2 } + set1.insert(200); + assert!(set1.is_subset(&set2)); // { 2 } { 1, 2 } + set1.insert(300); + assert!(!set1.is_subset(&set2)); // { 2, 3 } { 1, 2 } + set2.insert(300); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3 } + set2.insert(400); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3, 4 } + set2.remove(&100); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 2, 3, 4 } + set2.remove(&300); + assert!(!set1.is_subset(&set2)); // { 2, 3 } { 2, 4 } + set1.remove(&300); + assert!(set1.is_subset(&set2)); // { 2 } { 2, 4 } +} + +#[test] +fn test_bit_set_is_disjoint() { + let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01000000])); + let c = BitSet::new(); + let d = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00110000])); + + assert!(!a.is_disjoint(&d)); + assert!(!d.is_disjoint(&a)); + + assert!(a.is_disjoint(&b)); + assert!(a.is_disjoint(&c)); + assert!(b.is_disjoint(&a)); + assert!(b.is_disjoint(&c)); + assert!(c.is_disjoint(&a)); + assert!(c.is_disjoint(&b)); +} + +#[test] +fn test_bit_set_union_with() { + //a should grow to include larger elements + let mut a = BitSet::new(); + a.insert(0); + let mut b = BitSet::new(); + b.insert(5); + let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); + a.union_with(&b); + assert_eq!(a, expected); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); + let c = a.clone(); + a.union_with(&b); + b.union_with(&c); + assert_eq!(a.len(), 4); + assert_eq!(b.len(), 4); +} + +#[test] +fn test_bit_set_intersect_with() { + // Explicitly 0'ed bits + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert!(a.is_empty()); + assert!(b.is_empty()); + + // Uninitialized bits should behave like 0's + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::new(); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert!(a.is_empty()); + assert!(b.is_empty()); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert_eq!(a.len(), 2); + assert_eq!(b.len(), 2); +} + +#[test] +fn test_bit_set_difference_with() { + // Explicitly 0'ed bits + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + a.difference_with(&b); + assert!(a.is_empty()); + + // Uninitialized bits should behave like 0's + let mut a = BitSet::new(); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11111111])); + a.difference_with(&b); + assert!(a.is_empty()); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); + let c = a.clone(); + a.difference_with(&b); + b.difference_with(&c); + assert_eq!(a.len(), 1); + assert_eq!(b.len(), 1); +} + +#[test] +fn test_bit_set_symmetric_difference_with() { + //a should grow to include larger elements + let mut a = BitSet::new(); + a.insert(0); + a.insert(1); + let mut b = BitSet::new(); + b.insert(1); + b.insert(5); + let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); + a.symmetric_difference_with(&b); + assert_eq!(a, expected); + + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::new(); + let c = a.clone(); + a.symmetric_difference_with(&b); + assert_eq!(a, c); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101010])); + let c = a.clone(); + a.symmetric_difference_with(&b); + b.symmetric_difference_with(&c); + assert_eq!(a.len(), 2); + assert_eq!(b.len(), 2); +} + +#[test] +fn test_bit_set_eq() { + let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let c = BitSet::new(); + + assert!(a == a); + assert!(a != b); + assert!(a != c); + assert!(b == b); + assert!(b == c); + assert!(c == c); +} + +#[test] +fn test_bit_set_cmp() { + let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let c = BitSet::new(); + + assert_eq!(a.cmp(&b), Greater); + assert_eq!(a.cmp(&c), Greater); + assert_eq!(b.cmp(&a), Less); + assert_eq!(b.cmp(&c), Equal); + assert_eq!(c.cmp(&a), Less); + assert_eq!(c.cmp(&b), Equal); +} + +#[test] +fn test_bit_vec_remove() { + let mut a = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.remove(&1)); + + assert!(a.insert(100)); + assert!(a.remove(&100)); + + assert!(a.insert(1000)); + assert!(a.remove(&1000)); + a.shrink_to_fit(); +} + +#[test] +fn test_bit_vec_clone() { + let mut a = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(100)); + assert!(a.insert(1000)); + + let mut b = a.clone(); + + assert!(a == b); + + assert!(b.remove(&1)); + assert!(a.contains(&1)); + + assert!(a.remove(&1000)); + assert!(b.contains(&1000)); +} + +mod bench { + use std::collections::{BitSet, BitVec}; + use std::rand::{Rng, self}; + use std::u32; + + use test::{Bencher, black_box}; + + const BENCH_BITS : usize = 1 << 14; + + fn rng() -> rand::IsaacRng { + let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + rand::SeedableRng::from_seed(seed) + } + + #[bench] + fn bench_bit_vecset_small(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitSet::new(); + b.iter(|| { + for _ in 0..100 { + bit_vec.insert((r.next_u32() as usize) % u32::BITS as usize); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_vecset_big(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitSet::new(); + b.iter(|| { + for _ in 0..100 { + bit_vec.insert((r.next_u32() as usize) % BENCH_BITS); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_vecset_iter(b: &mut Bencher) { + let bit_vec = BitSet::from_bit_vec(BitVec::from_fn(BENCH_BITS, + |idx| {idx % 3 == 0})); + b.iter(|| { + let mut sum = 0; + for idx in &bit_vec { + sum += idx as usize; + } + sum + }) + } +} diff --git a/src/libcollectionstest/bit/vec.rs b/src/libcollectionstest/bit/vec.rs new file mode 100644 index 0000000000000..3826974d1ad6b --- /dev/null +++ b/src/libcollectionstest/bit/vec.rs @@ -0,0 +1,729 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BitVec; +use std::u32; + +#[test] +fn test_to_str() { + let zerolen = BitVec::new(); + assert_eq!(format!("{:?}", zerolen), ""); + + let eightbits = BitVec::from_elem(8, false); + assert_eq!(format!("{:?}", eightbits), "00000000") +} + +#[test] +fn test_0_elements() { + let act = BitVec::new(); + let exp = Vec::new(); + assert!(act.eq_vec(&exp)); + assert!(act.none() && act.all()); +} + +#[test] +fn test_1_element() { + let mut act = BitVec::from_elem(1, false); + assert!(act.eq_vec(&[false])); + assert!(act.none() && !act.all()); + act = BitVec::from_elem(1, true); + assert!(act.eq_vec(&[true])); + assert!(!act.none() && act.all()); +} + +#[test] +fn test_2_elements() { + let mut b = BitVec::from_elem(2, false); + b.set(0, true); + b.set(1, false); + assert_eq!(format!("{:?}", b), "10"); + assert!(!b.none() && !b.all()); +} + +#[test] +fn test_10_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(10, false); + assert!((act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false]))); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(10, true); + assert!((act.eq_vec(&[true, true, true, true, true, true, true, true, true, true]))); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(10, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + assert!((act.eq_vec(&[true, true, true, true, true, false, false, false, false, false]))); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(10, false); + act.set(5, true); + act.set(6, true); + act.set(7, true); + act.set(8, true); + act.set(9, true); + assert!((act.eq_vec(&[false, false, false, false, false, true, true, true, true, true]))); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(10, false); + act.set(0, true); + act.set(3, true); + act.set(6, true); + act.set(9, true); + assert!((act.eq_vec(&[true, false, false, true, false, false, true, false, false, true]))); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_31_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(31, false); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false])); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(31, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true])); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + act.set(5, true); + act.set(6, true); + act.set(7, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(16, true); + act.set(17, true); + act.set(18, true); + act.set(19, true); + act.set(20, true); + act.set(21, true); + act.set(22, true); + act.set(23, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(24, true); + act.set(25, true); + act.set(26, true); + act.set(27, true); + act.set(28, true); + act.set(29, true); + act.set(30, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, true, true, true, true, true, true, true])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(3, true); + act.set(17, true); + act.set(30, true); + assert!(act.eq_vec( + &[false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true])); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_32_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(32, false); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false])); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(32, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true])); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + act.set(5, true); + act.set(6, true); + act.set(7, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(16, true); + act.set(17, true); + act.set(18, true); + act.set(19, true); + act.set(20, true); + act.set(21, true); + act.set(22, true); + act.set(23, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(24, true); + act.set(25, true); + act.set(26, true); + act.set(27, true); + act.set(28, true); + act.set(29, true); + act.set(30, true); + act.set(31, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, true, true, true, true, true, true, true, true])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(3, true); + act.set(17, true); + act.set(30, true); + act.set(31, true); + assert!(act.eq_vec( + &[false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true, true])); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_33_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(33, false); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false])); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(33, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true])); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + act.set(5, true); + act.set(6, true); + act.set(7, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(16, true); + act.set(17, true); + act.set(18, true); + act.set(19, true); + act.set(20, true); + act.set(21, true); + act.set(22, true); + act.set(23, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(24, true); + act.set(25, true); + act.set(26, true); + act.set(27, true); + act.set(28, true); + act.set(29, true); + act.set(30, true); + act.set(31, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, true, true, true, true, true, true, true, true, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(3, true); + act.set(17, true); + act.set(30, true); + act.set(31, true); + act.set(32, true); + assert!(act.eq_vec( + &[false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true, true, true])); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_equal_differing_sizes() { + let v0 = BitVec::from_elem(10, false); + let v1 = BitVec::from_elem(11, false); + assert!(v0 != v1); +} + +#[test] +fn test_equal_greatly_differing_sizes() { + let v0 = BitVec::from_elem(10, false); + let v1 = BitVec::from_elem(110, false); + assert!(v0 != v1); +} + +#[test] +fn test_equal_sneaky_small() { + let mut a = BitVec::from_elem(1, false); + a.set(0, true); + + let mut b = BitVec::from_elem(1, true); + b.set(0, true); + + assert_eq!(a, b); +} + +#[test] +fn test_equal_sneaky_big() { + let mut a = BitVec::from_elem(100, false); + for i in 0..100 { + a.set(i, true); + } + + let mut b = BitVec::from_elem(100, true); + for i in 0..100 { + b.set(i, true); + } + + assert_eq!(a, b); +} + +#[test] +fn test_from_bytes() { + let bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); + let str = concat!("10110110", "00000000", "11111111"); + assert_eq!(format!("{:?}", bit_vec), str); +} + +#[test] +fn test_to_bytes() { + let mut bv = BitVec::from_elem(3, true); + bv.set(1, false); + assert_eq!(bv.to_bytes(), [0b10100000]); + + let mut bv = BitVec::from_elem(9, false); + bv.set(2, true); + bv.set(8, true); + assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]); +} + +#[test] +fn test_from_bools() { + let bools = vec![true, false, true, true]; + let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); + assert_eq!(format!("{:?}", bit_vec), "1011"); +} + +#[test] +fn test_to_bools() { + let bools = vec![false, false, true, false, false, true, true, false]; + assert_eq!(BitVec::from_bytes(&[0b00100110]).iter().collect::>(), bools); +} + +#[test] +fn test_bit_vec_iterator() { + let bools = vec![true, false, true, true]; + let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); + + assert_eq!(bit_vec.iter().collect::>(), bools); + + let long: Vec<_> = (0..10000).map(|i| i % 2 == 0).collect(); + let bit_vec: BitVec = long.iter().map(|n| *n).collect(); + assert_eq!(bit_vec.iter().collect::>(), long) +} + +#[test] +fn test_small_difference() { + let mut b1 = BitVec::from_elem(3, false); + let mut b2 = BitVec::from_elem(3, false); + b1.set(0, true); + b1.set(1, true); + b2.set(1, true); + b2.set(2, true); + assert!(b1.difference(&b2)); + assert!(b1[0]); + assert!(!b1[1]); + assert!(!b1[2]); +} + +#[test] +fn test_big_difference() { + let mut b1 = BitVec::from_elem(100, false); + let mut b2 = BitVec::from_elem(100, false); + b1.set(0, true); + b1.set(40, true); + b2.set(40, true); + b2.set(80, true); + assert!(b1.difference(&b2)); + assert!(b1[0]); + assert!(!b1[40]); + assert!(!b1[80]); +} + +#[test] +fn test_small_clear() { + let mut b = BitVec::from_elem(14, true); + assert!(!b.none() && b.all()); + b.clear(); + assert!(b.none() && !b.all()); +} + +#[test] +fn test_big_clear() { + let mut b = BitVec::from_elem(140, true); + assert!(!b.none() && b.all()); + b.clear(); + assert!(b.none() && !b.all()); +} + +#[test] +fn test_bit_vec_lt() { + let mut a = BitVec::from_elem(5, false); + let mut b = BitVec::from_elem(5, false); + + assert!(!(a < b) && !(b < a)); + b.set(2, true); + assert!(a < b); + a.set(3, true); + assert!(a < b); + a.set(2, true); + assert!(!(a < b) && b < a); + b.set(0, true); + assert!(a < b); +} + +#[test] +fn test_ord() { + let mut a = BitVec::from_elem(5, false); + let mut b = BitVec::from_elem(5, false); + + assert!(a <= b && a >= b); + a.set(1, true); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + b.set(1, true); + b.set(2, true); + assert!(b > a && b >= a); + assert!(a < b && a <= b); +} + + +#[test] +fn test_small_bit_vec_tests() { + let v = BitVec::from_bytes(&[0]); + assert!(!v.all()); + assert!(!v.any()); + assert!(v.none()); + + let v = BitVec::from_bytes(&[0b00010100]); + assert!(!v.all()); + assert!(v.any()); + assert!(!v.none()); + + let v = BitVec::from_bytes(&[0xFF]); + assert!(v.all()); + assert!(v.any()); + assert!(!v.none()); +} + +#[test] +fn test_big_bit_vec_tests() { + let v = BitVec::from_bytes(&[ // 88 bits + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0]); + assert!(!v.all()); + assert!(!v.any()); + assert!(v.none()); + + let v = BitVec::from_bytes(&[ // 88 bits + 0, 0, 0b00010100, 0, + 0, 0, 0, 0b00110100, + 0, 0, 0]); + assert!(!v.all()); + assert!(v.any()); + assert!(!v.none()); + + let v = BitVec::from_bytes(&[ // 88 bits + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF]); + assert!(v.all()); + assert!(v.any()); + assert!(!v.none()); +} + +#[test] +fn test_bit_vec_push_pop() { + let mut s = BitVec::from_elem(5 * u32::BITS as usize - 2, false); + assert_eq!(s.len(), 5 * u32::BITS as usize - 2); + assert_eq!(s[5 * u32::BITS as usize - 3], false); + s.push(true); + s.push(true); + assert_eq!(s[5 * u32::BITS as usize - 2], true); + assert_eq!(s[5 * u32::BITS as usize - 1], true); + // Here the internal vector will need to be extended + s.push(false); + assert_eq!(s[5 * u32::BITS as usize], false); + s.push(false); + assert_eq!(s[5 * u32::BITS as usize + 1], false); + assert_eq!(s.len(), 5 * u32::BITS as usize + 2); + // Pop it all off + assert_eq!(s.pop(), Some(false)); + assert_eq!(s.pop(), Some(false)); + assert_eq!(s.pop(), Some(true)); + assert_eq!(s.pop(), Some(true)); + assert_eq!(s.len(), 5 * u32::BITS as usize - 2); +} + +#[test] +fn test_bit_vec_truncate() { + let mut s = BitVec::from_elem(5 * u32::BITS as usize, true); + + assert_eq!(s, BitVec::from_elem(5 * u32::BITS as usize, true)); + assert_eq!(s.len(), 5 * u32::BITS as usize); + s.truncate(4 * u32::BITS as usize); + assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true)); + assert_eq!(s.len(), 4 * u32::BITS as usize); + // Truncating to a size > s.len() should be a noop + s.truncate(5 * u32::BITS as usize); + assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true)); + assert_eq!(s.len(), 4 * u32::BITS as usize); + s.truncate(3 * u32::BITS as usize - 10); + assert_eq!(s, BitVec::from_elem(3 * u32::BITS as usize - 10, true)); + assert_eq!(s.len(), 3 * u32::BITS as usize - 10); + s.truncate(0); + assert_eq!(s, BitVec::from_elem(0, true)); + assert_eq!(s.len(), 0); +} + +#[test] +fn test_bit_vec_reserve() { + let mut s = BitVec::from_elem(5 * u32::BITS as usize, true); + // Check capacity + assert!(s.capacity() >= 5 * u32::BITS as usize); + s.reserve(2 * u32::BITS as usize); + assert!(s.capacity() >= 7 * u32::BITS as usize); + s.reserve(7 * u32::BITS as usize); + assert!(s.capacity() >= 12 * u32::BITS as usize); + s.reserve_exact(7 * u32::BITS as usize); + assert!(s.capacity() >= 12 * u32::BITS as usize); + s.reserve(7 * u32::BITS as usize + 1); + assert!(s.capacity() >= 12 * u32::BITS as usize + 1); + // Check that length hasn't changed + assert_eq!(s.len(), 5 * u32::BITS as usize); + s.push(true); + s.push(false); + s.push(true); + assert_eq!(s[5 * u32::BITS as usize - 1], true); + assert_eq!(s[5 * u32::BITS as usize - 0], true); + assert_eq!(s[5 * u32::BITS as usize + 1], false); + assert_eq!(s[5 * u32::BITS as usize + 2], true); +} + +#[test] +fn test_bit_vec_grow() { + let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010]); + bit_vec.grow(32, true); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF])); + bit_vec.grow(64, false); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])); + bit_vec.grow(16, true); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF])); +} + +#[test] +fn test_bit_vec_extend() { + let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); + let ext = BitVec::from_bytes(&[0b01001001, 0b10010010, 0b10111101]); + bit_vec.extend(ext.iter()); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111, + 0b01001001, 0b10010010, 0b10111101])); +} + +mod bench { + use std::collections::BitVec; + use std::u32; + use std::rand::{Rng, self}; + + use test::{Bencher, black_box}; + + const BENCH_BITS : usize = 1 << 14; + + fn rng() -> rand::IsaacRng { + let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + rand::SeedableRng::from_seed(seed) + } + + #[bench] + fn bench_usize_small(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = 0 as usize; + b.iter(|| { + for _ in 0..100 { + bit_vec |= 1 << ((r.next_u32() as usize) % u32::BITS as usize); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_set_big_fixed(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + for _ in 0..100 { + bit_vec.set((r.next_u32() as usize) % BENCH_BITS, true); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_set_big_variable(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + for _ in 0..100 { + bit_vec.set((r.next_u32() as usize) % BENCH_BITS, r.gen()); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_set_small(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitVec::from_elem(u32::BITS as usize, false); + b.iter(|| { + for _ in 0..100 { + bit_vec.set((r.next_u32() as usize) % u32::BITS as usize, true); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_vec_big_union(b: &mut Bencher) { + let mut b1 = BitVec::from_elem(BENCH_BITS, false); + let b2 = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + b1.union(&b2) + }) + } + + #[bench] + fn bench_bit_vec_small_iter(b: &mut Bencher) { + let bit_vec = BitVec::from_elem(u32::BITS as usize, false); + b.iter(|| { + let mut sum = 0; + for _ in 0..10 { + for pres in &bit_vec { + sum += pres as usize; + } + } + sum + }) + } + + #[bench] + fn bench_bit_vec_big_iter(b: &mut Bencher) { + let bit_vec = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + let mut sum = 0; + for pres in &bit_vec { + sum += pres as usize; + } + sum + }) + } +} diff --git a/src/libcollectionstest/btree/map.rs b/src/libcollectionstest/btree/map.rs new file mode 100644 index 0000000000000..10d69c9f5ece6 --- /dev/null +++ b/src/libcollectionstest/btree/map.rs @@ -0,0 +1,299 @@ +// 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 or the MIT license +// , 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::{Excluded, Included, Unbounded, self}; +use std::collections::btree_map::Entry::{Occupied, Vacant}; +use std::iter::range_inclusive; + +#[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(size: usize, mut iter: T) where T: Iterator { + 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(size: usize, mut iter: T) where T: Iterator { + 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_iter_mixed() { + let size = 10000; + + // Forwards + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test(size: usize, mut iter: T) + where T: Iterator + 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(Included(&2), Unbounded).zip(2..size) { + assert_eq!(k, i); + assert_eq!(v, i); + j += 1; + } + assert_eq!(j, size - 2); +} + +#[test] +fn test_range_1000() { + let size = 1000; + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test(map: &BTreeMap, 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() { + 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 = range_inclusive(i, j).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_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); +} + +mod bench { + use std::collections::BTreeMap; + use std::rand::{Rng, weak_rng}; + + use test::{Bencher, black_box}; + + map_insert_rand_bench!{insert_rand_100, 100, BTreeMap} + map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap} + + map_insert_seq_bench!{insert_seq_100, 100, BTreeMap} + map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap} + + map_find_rand_bench!{find_rand_100, 100, BTreeMap} + map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap} + + map_find_seq_bench!{find_seq_100, 100, BTreeMap} + map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap} + + fn bench_iter(b: &mut Bencher, size: i32) { + let mut map = BTreeMap::::new(); + let mut rng = weak_rng(); + + for _ in 0..size { + map.insert(rng.gen(), rng.gen()); + } + + b.iter(|| { + for entry in &map { + black_box(entry); + } + }); + } + + #[bench] + pub fn iter_20(b: &mut Bencher) { + bench_iter(b, 20); + } + + #[bench] + pub fn iter_1000(b: &mut Bencher) { + bench_iter(b, 1000); + } + + #[bench] + pub fn iter_100000(b: &mut Bencher) { + bench_iter(b, 100000); + } +} diff --git a/src/libcollectionstest/btree/mod.rs b/src/libcollectionstest/btree/mod.rs new file mode 100644 index 0000000000000..0db48f3ce9edb --- /dev/null +++ b/src/libcollectionstest/btree/mod.rs @@ -0,0 +1,12 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod map; +mod set; diff --git a/src/libcollectionstest/btree/set.rs b/src/libcollectionstest/btree/set.rs new file mode 100644 index 0000000000000..488f0d756d329 --- /dev/null +++ b/src/libcollectionstest/btree/set.rs @@ -0,0 +1,180 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BTreeSet; +use std::hash::{SipHasher, self}; + +#[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::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); +} + +struct Counter<'a, 'b> { + i: &'a mut usize, + expected: &'b [i32], +} + +impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> { + type Output = bool; + + extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool { + assert_eq!(x, self.expected[*self.i]); + *self.i += 1; + true + } +} + +fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) where + // FIXME Replace Counter with `Box _>` + F: FnOnce(&BTreeSet, &BTreeSet, Counter) -> 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, Counter { i: &mut i, expected: expected }); + 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.iter()); + + // FIXME: #5801: this needs a type hint to compile... + let result: Option<(&usize, & &'static str)> = z.next(); + assert_eq!(result.unwrap(), (&5, &("bar"))); + + let result: Option<(&usize, & &'static str)> = z.next(); + assert_eq!(result.unwrap(), (&11, &("foo"))); + + let result: Option<(&usize, & &'static str)> = z.next(); + assert!(result.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::::new(); + + set.insert(1); + set.insert(2); + + let set_str = format!("{:?}", set); + + assert_eq!(set_str, "{1, 2}"); + assert_eq!(format!("{:?}", empty), "{}"); +} diff --git a/src/libcollectionstest/enum_set.rs b/src/libcollectionstest/enum_set.rs new file mode 100644 index 0000000000000..a740c531c89d2 --- /dev/null +++ b/src/libcollectionstest/enum_set.rs @@ -0,0 +1,240 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::EnumSet; + +#[derive(Copy, PartialEq, Debug)] +#[repr(usize)] +enum Foo { + A, B, C +} + +impl CLike for Foo { + fn to_usize(&self) -> usize { + *self as usize + } + + fn from_usize(v: usize) -> Foo { + unsafe { mem::transmute(v) } + } +} + +#[test] +fn test_new() { + let e: EnumSet = EnumSet::new(); + assert!(e.is_empty()); +} + +#[test] +fn test_show() { + let mut e = EnumSet::new(); + assert!(format!("{:?}", e) == "{}"); + e.insert(A); + assert!(format!("{:?}", e) == "{A}"); + e.insert(C); + assert!(format!("{:?}", e) == "{A, C}"); +} + +#[test] +fn test_len() { + let mut e = EnumSet::new(); + assert_eq!(e.len(), 0); + e.insert(A); + e.insert(B); + e.insert(C); + assert_eq!(e.len(), 3); + e.remove(&A); + assert_eq!(e.len(), 2); + e.clear(); + assert_eq!(e.len(), 0); +} + +/////////////////////////////////////////////////////////////////////////// +// intersect + +#[test] +fn test_two_empties_do_not_intersect() { + let e1: EnumSet = EnumSet::new(); + let e2: EnumSet = EnumSet::new(); + assert!(e1.is_disjoint(&e2)); +} + +#[test] +fn test_empty_does_not_intersect_with_full() { + let e1: EnumSet = EnumSet::new(); + + let mut e2: EnumSet = EnumSet::new(); + e2.insert(A); + e2.insert(B); + e2.insert(C); + + assert!(e1.is_disjoint(&e2)); +} + +#[test] +fn test_disjoint_intersects() { + let mut e1: EnumSet = EnumSet::new(); + e1.insert(A); + + let mut e2: EnumSet = EnumSet::new(); + e2.insert(B); + + assert!(e1.is_disjoint(&e2)); +} + +#[test] +fn test_overlapping_intersects() { + let mut e1: EnumSet = EnumSet::new(); + e1.insert(A); + + let mut e2: EnumSet = EnumSet::new(); + e2.insert(A); + e2.insert(B); + + assert!(!e1.is_disjoint(&e2)); +} + +/////////////////////////////////////////////////////////////////////////// +// contains and contains_elem + +#[test] +fn test_superset() { + let mut e1: EnumSet = EnumSet::new(); + e1.insert(A); + + let mut e2: EnumSet = EnumSet::new(); + e2.insert(A); + e2.insert(B); + + let mut e3: EnumSet = EnumSet::new(); + e3.insert(C); + + assert!(e1.is_subset(&e2)); + assert!(e2.is_superset(&e1)); + assert!(!e3.is_superset(&e2)); + assert!(!e2.is_superset(&e3)) +} + +#[test] +fn test_contains() { + let mut e1: EnumSet = EnumSet::new(); + e1.insert(A); + assert!(e1.contains(&A)); + assert!(!e1.contains(&B)); + assert!(!e1.contains(&C)); + + e1.insert(A); + e1.insert(B); + assert!(e1.contains(&A)); + assert!(e1.contains(&B)); + assert!(!e1.contains(&C)); +} + +/////////////////////////////////////////////////////////////////////////// +// iter + +#[test] +fn test_iterator() { + let mut e1: EnumSet = EnumSet::new(); + + let elems: ::vec::Vec = e1.iter().collect(); + assert!(elems.is_empty()); + + e1.insert(A); + let elems: ::vec::Vec<_> = e1.iter().collect(); + assert_eq!([A], elems); + + e1.insert(C); + let elems: ::vec::Vec<_> = e1.iter().collect(); + assert_eq!([A,C], elems); + + e1.insert(C); + let elems: ::vec::Vec<_> = e1.iter().collect(); + assert_eq!([A,C], elems); + + e1.insert(B); + let elems: ::vec::Vec<_> = e1.iter().collect(); + assert_eq!([A,B,C], elems); +} + +/////////////////////////////////////////////////////////////////////////// +// operators + +#[test] +fn test_operators() { + let mut e1: EnumSet = EnumSet::new(); + e1.insert(A); + e1.insert(C); + + let mut e2: EnumSet = EnumSet::new(); + e2.insert(B); + e2.insert(C); + + let e_union = e1 | e2; + let elems: ::vec::Vec<_> = e_union.iter().collect(); + assert_eq!([A,B,C], elems); + + let e_intersection = e1 & e2; + let elems: ::vec::Vec<_> = e_intersection.iter().collect(); + assert_eq!([C], elems); + + // Another way to express intersection + let e_intersection = e1 - (e1 - e2); + let elems: ::vec::Vec<_> = e_intersection.iter().collect(); + assert_eq!([C], elems); + + let e_subtract = e1 - e2; + let elems: ::vec::Vec<_> = e_subtract.iter().collect(); + assert_eq!([A], elems); + + // Bitwise XOR of two sets, aka symmetric difference + let e_symmetric_diff = e1 ^ e2; + let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); + assert_eq!([A,B], elems); + + // Another way to express symmetric difference + let e_symmetric_diff = (e1 - e2) | (e2 - e1); + let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); + assert_eq!([A,B], elems); + + // Yet another way to express symmetric difference + let e_symmetric_diff = (e1 | e2) - (e1 & e2); + let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); + assert_eq!([A,B], elems); +} + +#[test] +#[should_panic] +fn test_overflow() { + #[allow(dead_code)] + #[derive(Copy)] + #[repr(usize)] + enum Bar { + V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, + V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, + V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, + V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, + V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, + V50, V51, V52, V53, V54, V55, V56, V57, V58, V59, + V60, V61, V62, V63, V64, V65, V66, V67, V68, V69, + } + + impl CLike for Bar { + fn to_usize(&self) -> usize { + *self as usize + } + + fn from_usize(v: usize) -> Bar { + unsafe { mem::transmute(v) } + } + } + let mut set = EnumSet::new(); + set.insert(Bar::V64); +} diff --git a/src/libcollectionstest/fmt.rs b/src/libcollectionstest/fmt.rs new file mode 100644 index 0000000000000..9a9aa71b58bfa --- /dev/null +++ b/src/libcollectionstest/fmt.rs @@ -0,0 +1,17 @@ +// 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 or the MIT license +// , 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.as_slice(), "Hello, world!"); +} diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs new file mode 100644 index 0000000000000..4cf1d01a4ee2a --- /dev/null +++ b/src/libcollectionstest/lib.rs @@ -0,0 +1,44 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(deprecated)] +#![feature(box_syntax)] +#![feature(collections)] +#![feature(core)] +#![feature(hash)] +#![feature(rand)] +#![feature(rustc_private)] +#![feature(str_words)] +#![feature(test)] +#![feature(unboxed_closures)] +#![feature(unicode)] +#![feature(unsafe_destructor)] + +#[macro_use] extern crate log; + +extern crate collections; +extern crate test; +extern crate unicode; + +#[cfg(test)] #[macro_use] mod bench; + +mod binary_heap; +mod bit; +mod btree; +// FIXME(japaric) privacy +//mod enum_set; +mod fmt; +mod linked_list; +mod slice; +mod str; +mod string; +mod vec_deque; +mod vec_map; +mod vec; diff --git a/src/libcollectionstest/linked_list.rs b/src/libcollectionstest/linked_list.rs new file mode 100644 index 0000000000000..95d49885b3b2d --- /dev/null +++ b/src/libcollectionstest/linked_list.rs @@ -0,0 +1,589 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::LinkedList; +use std::hash::{SipHasher, self}; + +use test; + +// FIXME(japaric) privacy +/* +pub fn check_links(list: &LinkedList) { + let mut len = 0; + let mut last_ptr: Option<&Node> = None; + let mut node_ptr: &Node; + match list.list_head { + None => { assert_eq!(0, list.length); return } + Some(ref node) => node_ptr = &**node, + } + loop { + match (last_ptr, node_ptr.prev.resolve_immut()) { + (None , None ) => {} + (None , _ ) => panic!("prev link for list_head"), + (Some(p), Some(pptr)) => { + assert_eq!(p as *const Node, pptr as *const Node); + } + _ => panic!("prev link is none, not good"), + } + match node_ptr.next { + Some(ref next) => { + last_ptr = Some(node_ptr); + node_ptr = &**next; + len += 1; + } + None => { + len += 1; + break; + } + } + } + assert_eq!(len, list.length); +} +*/ + +#[test] +fn test_basic() { + let mut m = LinkedList::>::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 { + list_from(&[0,1,2,3,4,5,6]) +} + +#[cfg(test)] +fn list_from(v: &[T]) -> LinkedList { + v.iter().cloned().collect() +} + +// FIXME(japaric) privacy +/* +#[test] +fn test_append() { + // Empty to empty + { + let mut m = LinkedList::::new(); + let mut n = LinkedList::new(); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 0); + assert_eq!(n.len(), 0); + } + // Non-empty to empty + { + let mut m = LinkedList::new(); + let mut n = LinkedList::new(); + n.push_back(2); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + assert_eq!(n.len(), 0); + check_links(&m); + } + // Empty to non-empty + { + let mut m = LinkedList::new(); + let mut n = LinkedList::new(); + m.push_back(2); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + check_links(&m); + } + + // Non-empty to non-empty + let v = vec![1,2,3,4,5]; + let u = vec![9,8,1,2,3,4,5]; + let mut m = list_from(&v); + let mut n = list_from(&u); + m.append(&mut n); + check_links(&m); + let mut sum = v; + sum.push_all(&u); + assert_eq!(sum.len(), m.len()); + for elt in sum { + assert_eq!(m.pop_front(), Some(elt)) + } + assert_eq!(n.len(), 0); + // let's make sure it's working properly, since we + // did some direct changes to private members + n.push_back(3); + assert_eq!(n.len(), 1); + assert_eq!(n.pop_front(), Some(3)); + check_links(&n); +} +*/ + +#[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()); +} + +// FIXME(japaric) privacy +/* +#[test] +fn test_insert_prev() { + let mut m = list_from(&[0,2,4,6,8]); + let len = m.len(); + { + let mut it = m.iter_mut(); + it.insert_next(-2); + loop { + match it.next() { + None => break, + Some(elt) => { + it.insert_next(*elt + 1); + match it.peek_next() { + Some(x) => assert_eq!(*x, *elt + 2), + None => assert_eq!(8, *elt), + } + } + } + } + it.insert_next(0); + it.insert_next(1); + } + check_links(&m); + assert_eq!(m.len(), 3 + len * 2); + assert_eq!(m.into_iter().collect::>(), [-2,0,1,2,3,4,5,6,7,8,9,0,1]); +} +*/ + +#[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()); +} + +// FIXME(japaric) privacy +/* +#[test] +fn test_send() { + let n = list_from(&[1,2,3]); + thread::spawn(move || { + check_links(&n); + let a: &[_] = &[&1,&2,&3]; + assert_eq!(a, n.iter().collect::>()); + }).join().ok().unwrap(); +} +*/ + +#[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::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&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::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&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); +} + +// FIXME(japaric) privacy +/* +#[test] +fn test_fuzz() { + for _ in 0..25 { + fuzz_test(3); + fuzz_test(16); + fuzz_test(189); + } +} +*/ + +#[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\"]"); +} + +// FIXME(japaric) privacy +/* +#[cfg(test)] +fn fuzz_test(sz: i32) { + let mut m: LinkedList<_> = LinkedList::new(); + let mut v = vec![]; + for i in 0..sz { + check_links(&m); + let r: u8 = rand::random(); + match r % 6 { + 0 => { + m.pop_back(); + v.pop(); + } + 1 => { + if !v.is_empty() { + m.pop_front(); + v.remove(0); + } + } + 2 | 4 => { + m.push_front(-i); + v.insert(0, -i); + } + 3 | 5 | _ => { + m.push_back(i); + v.push(i); + } + } + } + + check_links(&m); + + let mut i = 0; + for (a, &b) in m.into_iter().zip(v.iter()) { + i += 1; + assert_eq!(a, b); + } + assert_eq!(i, v.len()); +} +*/ + +#[bench] +fn bench_collect_into(b: &mut test::Bencher) { + let v = &[0; 64]; + b.iter(|| { + let _: LinkedList<_> = v.iter().cloned().collect(); + }) +} + +#[bench] +fn bench_push_front(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_front(0); + }) +} + +#[bench] +fn bench_push_back(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_back(0); + }) +} + +#[bench] +fn bench_push_back_pop_back(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_back(0); + m.pop_back(); + }) +} + +#[bench] +fn bench_push_front_pop_front(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_front(0); + m.pop_front(); + }) +} + +#[bench] +fn bench_iter(b: &mut test::Bencher) { + let v = &[0; 128]; + let m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter().count() == 128); + }) +} +#[bench] +fn bench_iter_mut(b: &mut test::Bencher) { + let v = &[0; 128]; + let mut m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter_mut().count() == 128); + }) +} +#[bench] +fn bench_iter_rev(b: &mut test::Bencher) { + let v = &[0; 128]; + let m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter().rev().count() == 128); + }) +} +#[bench] +fn bench_iter_mut_rev(b: &mut test::Bencher) { + let v = &[0; 128]; + let mut m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter_mut().rev().count() == 128); + }) +} diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs new file mode 100644 index 0000000000000..7d50a1a13f2ab --- /dev/null +++ b/src/libcollectionstest/slice.rs @@ -0,0 +1,1627 @@ +// 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 or the MIT license +// , 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::default::Default; +use std::iter::RandomAccessIterator; +use std::mem; +use std::rand::{Rng, thread_rng}; +use std::rc::Rc; +use std::slice::ElementSwaps; + +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.as_slice(); + 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::(), 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_tail() { + let mut a = vec![11]; + let b: &[i32] = &[]; + assert_eq!(a.tail(), b); + a = vec![11, 12]; + let b: &[i32] = &[12]; + assert_eq!(a.tail(), b); +} + +#[test] +fn test_tail_mut() { + let mut a = vec![11]; + let b: &mut [i32] = &mut []; + assert!(a.tail_mut() == b); + a = vec![11, 12]; + let b: &mut [_] = &mut [12]; + assert!(a.tail_mut() == b); +} + +#[test] +#[should_panic] +fn test_tail_empty() { + let a = Vec::::new(); + a.tail(); +} + +#[test] +#[should_panic] +fn test_tail_mut_empty() { + let mut a = Vec::::new(); + a.tail_mut(); +} + +#[test] +fn test_init() { + let mut a = vec![11]; + let b: &[i32] = &[]; + assert_eq!(a.init(), b); + a = vec![11, 12]; + let b: &[_] = &[11]; + assert_eq!(a.init(), b); +} + +#[test] +fn test_init_mut() { + let mut a = vec![11]; + let b: &mut [i32] = &mut []; + assert!(a.init_mut() == b); + a = vec![11, 12]; + let b: &mut [_] = &mut [11]; + assert!(a.init_mut() == b); +} + +#[test] +#[should_panic] +fn test_init_empty() { + let a = Vec::::new(); + a.init(); +} + +#[test] +#[should_panic] +fn test_init_mut_empty() { + let mut a = Vec::::new(); + a.init_mut(); +} + +#[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> = Vec::new(); + v.push(box 0u8); + v.push(box 0u8); + v.push(box 0u8); + 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> = 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> = 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_dedup() { + fn case(a: Vec, b: Vec) { + 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_unique() { + let mut v0: Vec> = vec![box 1, box 1, box 2, box 3]; + v0.dedup(); + let mut v1: Vec> = vec![box 1, box 2, box 2, box 3]; + v1.dedup(); + let mut v2: Vec> = 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 test_dedup_shared() { + let mut v0: Vec> = vec![box 1, box 1, box 2, box 3]; + v0.dedup(); + let mut v1: Vec> = vec![box 1, box 2, box 2, box 3]; + v1.dedup(); + let mut v2: Vec> = vec![box 1, box 2, box 3, box 3]; + v2.dedup(); + /* + * If the pointers were leaked or otherwise misused, valgrind and/or + * rt should raise errors. + */ +} + +#[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_element_swaps() { + let mut v = [1, 2, 3]; + for (i, (a, b)) in ElementSwaps::new(v.len()).enumerate() { + v.swap(a, b); + match i { + 0 => assert!(v == [1, 3, 2]), + 1 => assert!(v == [3, 1, 2]), + 2 => assert!(v == [3, 2, 1]), + 3 => assert!(v == [2, 3, 1]), + 4 => assert!(v == [2, 1, 3]), + 5 => assert!(v == [1, 2, 3]), + _ => panic!(), + } + } +} + +// FIXME(japaric) privacy +/* +#[test] +fn test_permutations() { + { + let v: [i32; 0] = []; + let mut it = v.permutations(); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 1); + assert_eq!(max_opt.unwrap(), 1); + assert_eq!(it.next(), Some(v.to_vec())); + assert_eq!(it.next(), None); + } + { + let v = ["Hello".to_string()]; + let mut it = v.permutations(); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 1); + assert_eq!(max_opt.unwrap(), 1); + assert_eq!(it.next(), Some(v.to_vec())); + assert_eq!(it.next(), None); + } + { + let v = [1, 2, 3]; + let mut it = v.permutations(); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 3*2); + assert_eq!(max_opt.unwrap(), 3*2); + assert_eq!(it.next(), Some(vec![1,2,3])); + assert_eq!(it.next(), Some(vec![1,3,2])); + assert_eq!(it.next(), Some(vec![3,1,2])); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 3); + assert_eq!(max_opt.unwrap(), 3); + assert_eq!(it.next(), Some(vec![3,2,1])); + assert_eq!(it.next(), Some(vec![2,3,1])); + assert_eq!(it.next(), Some(vec![2,1,3])); + assert_eq!(it.next(), None); + } + { + // check that we have N! permutations + let v = ['A', 'B', 'C', 'D', 'E', 'F']; + let mut amt = 0; + let mut it = v.permutations(); + let (min_size, max_opt) = it.size_hint(); + for _perm in it.by_ref() { + amt += 1; + } + assert_eq!(amt, it.swaps.swaps_made); + assert_eq!(amt, min_size); + assert_eq!(amt, 2 * 3 * 4 * 5 * 6); + assert_eq!(amt, max_opt.unwrap()); + } +} +*/ + +#[test] +fn test_lexicographic_permutations() { + let v : &mut[_] = &mut[1, 2, 3, 4, 5]; + assert!(v.prev_permutation() == false); + assert!(v.next_permutation()); + let b: &mut[_] = &mut[1, 2, 3, 5, 4]; + assert!(v == b); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[1, 2, 3, 4, 5]; + assert!(v == b); + assert!(v.next_permutation()); + assert!(v.next_permutation()); + let b: &mut[_] = &mut[1, 2, 4, 3, 5]; + assert!(v == b); + assert!(v.next_permutation()); + let b: &mut[_] = &mut[1, 2, 4, 5, 3]; + assert!(v == b); + + let v : &mut[_] = &mut[1, 0, 0, 0]; + assert!(v.next_permutation() == false); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[0, 1, 0, 0]; + assert!(v == b); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[0, 0, 1, 0]; + assert!(v == b); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[0, 0, 0, 1]; + assert!(v == b); + assert!(v.prev_permutation() == false); +} + +#[test] +fn test_lexicographic_permutations_empty_and_short() { + let empty : &mut[i32] = &mut[]; + assert!(empty.next_permutation() == false); + let b: &mut[i32] = &mut[]; + assert!(empty == b); + assert!(empty.prev_permutation() == false); + assert!(empty == b); + + let one_elem : &mut[_] = &mut[4]; + assert!(one_elem.prev_permutation() == false); + let b: &mut[_] = &mut[4]; + assert!(one_elem == b); + assert!(one_elem.next_permutation() == false); + assert!(one_elem == b); + + let two_elem : &mut[_] = &mut[1, 2]; + assert!(two_elem.prev_permutation() == false); + let b : &mut[_] = &mut[1, 2]; + let c : &mut[_] = &mut[2, 1]; + assert!(two_elem == b); + assert!(two_elem.next_permutation()); + assert!(two_elem == c); + assert!(two_elem.next_permutation() == false); + assert!(two_elem == c); + assert!(two_elem.prev_permutation()); + assert!(two_elem == b); + assert!(two_elem.prev_permutation() == false); + assert!(two_elem == b); +} + +#[test] +fn test_position_elem() { + assert!([].position_elem(&1).is_none()); + + let v1 = vec![1, 2, 3, 3, 2, 5]; + assert_eq!(v1.position_elem(&1), Some(0)); + assert_eq!(v1.position_elem(&2), Some(1)); + assert_eq!(v1.position_elem(&5), Some(5)); + assert!(v1.position_elem(&4).is_none()); +} + +#[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::::new(); + v3.reverse(); + assert!(v3.is_empty()); +} + +#[test] +fn test_sort() { + for len in 4..25 { + for _ in 0..100 { + let mut v: Vec<_> = thread_rng().gen_iter::().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])); + } + } + + // shouldn't panic + let mut v: [i32; 0] = []; + v.sort(); + + let mut v = [0xDEADBEEFu64]; + v.sort(); + assert!(v == [0xDEADBEEF]); +} + +#[test] +fn test_sort_stability() { + for len in 4..25 { + 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::() % 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; 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.connect(&0), [1, 0, 2, 3]); + let v: &[&[_]] = &[&[1], &[2], &[3]]; + assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]); +} + +#[test] +fn test_connect() { + let v: [Vec; 0] = []; + assert_eq!(v.connect(&0), []); + assert_eq!([vec![1], vec![2, 3]].connect(&0), [1, 0, 2, 3]); + assert_eq!([vec![1], vec![2], vec![3]].connect(&0), [1, 0, 2, 0, 3]); + + let v: [&[_]; 2] = [&[1], &[2, 3]]; + assert_eq!(v.connect(&0), [1, 0, 2, 3]); + let v: [&[_]; 3] = [&[1], &[2], &[3]]; + assert_eq!(v.connect(&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.slice(1, 3); + assert_eq!(v.len(), 2); + assert_eq!(v[0], 2); + assert_eq!(v[1], 3); +} + +#[test] +#[should_panic] +fn test_permute_fail() { + let v: [(Box<_>, Rc<_>); 4] = + [(box 0, Rc::new(0)), (box 0, Rc::new(0)), + (box 0, Rc::new(0)), (box 0, Rc::new(0))]; + let mut i = 0; + for _ in v.permutations() { + if i == 2 { + panic!() + } + i += 1; + } +} + +#[test] +fn test_total_ord() { + let c = &[1, 2, 3]; + [1, 2, 3, 4][..].cmp(c) == Greater; + let c = &[1, 2, 3, 4]; + [1, 2, 3][..].cmp(c) == Less; + let c = &[1, 2, 3, 6]; + [1, 2, 3, 4][..].cmp(c) == Equal; + let c = &[1, 2, 3, 4, 5, 6]; + [1, 2, 3, 4, 5, 5, 5, 5][..].cmp(c) == Less; + let c = &[1, 2, 3, 4]; + [2, 2][..].cmp(c) == Greater; +} + +#[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_random_access_iterator() { + let xs = [1, 2, 5, 10, 11]; + let mut it = xs.iter(); + + assert_eq!(it.indexable(), 5); + assert_eq!(it.idx(0).unwrap(), &1); + assert_eq!(it.idx(2).unwrap(), &5); + assert_eq!(it.idx(4).unwrap(), &11); + assert!(it.idx(5).is_none()); + + assert_eq!(it.next().unwrap(), &1); + assert_eq!(it.indexable(), 4); + assert_eq!(it.idx(0).unwrap(), &2); + assert_eq!(it.idx(3).unwrap(), &11); + assert!(it.idx(4).is_none()); + + assert_eq!(it.next().unwrap(), &2); + assert_eq!(it.indexable(), 3); + assert_eq!(it.idx(1).unwrap(), &10); + assert!(it.idx(3).is_none()); + + assert_eq!(it.next().unwrap(), &5); + assert_eq!(it.indexable(), 2); + assert_eq!(it.idx(1).unwrap(), &11); + + assert_eq!(it.next().unwrap(), &10); + assert_eq!(it.indexable(), 1); + assert_eq!(it.idx(0).unwrap(), &11); + assert!(it.idx(1).is_none()); + + assert_eq!(it.next().unwrap(), &11); + assert_eq!(it.indexable(), 0); + assert!(it.idx(0).is_none()); + + 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_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_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::>(), + splits); + let splits: &[&[_]] = &[&[], &[2,3,4,5]]; + assert_eq!(xs.split(|x| *x == 1).collect::>(), + splits); + let splits: &[&[_]] = &[&[1,2,3,4], &[]]; + assert_eq!(xs.split(|x| *x == 5).collect::>(), + splits); + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.split(|x| *x == 10).collect::>(), + splits); + let splits: &[&[_]] = &[&[], &[], &[], &[], &[], &[]]; + assert_eq!(xs.split(|_| true).collect::>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split(|x| *x == 5).collect::>(), splits); +} + +#[test] +fn test_splitnator() { + let xs = &[1,2,3,4,5]; + + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.splitn(0, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&[_]] = &[&[1], &[3,4,5]]; + assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&[_]] = &[&[], &[], &[], &[4,5]]; + assert_eq!(xs.splitn(3, |_| true).collect::>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.splitn(1, |x| *x == 5).collect::>(), 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(0, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&mut[_]] = &[&mut [1], &mut [3,4,5]]; + assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&mut[_]] = &[&mut [], &mut [], &mut [], &mut [4,5]]; + assert_eq!(xs.splitn_mut(3, |_| true).collect::>(), + splits); + + let xs: &mut [i32] = &mut []; + let splits: &[&mut[i32]] = &[&mut []]; + assert_eq!(xs.splitn_mut(1, |x| *x == 5).collect::>(), + 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::>(), + splits); + let splits: &[&[_]] = &[&[2,3,4,5], &[]]; + assert_eq!(xs.split(|x| *x == 1).rev().collect::>(), + splits); + let splits: &[&[_]] = &[&[], &[1,2,3,4]]; + assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), + splits); + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.split(|x| *x == 10).rev().collect::>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), splits); +} + +#[test] +fn test_rsplitnator() { + let xs = &[1,2,3,4,5]; + + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.rsplitn(0, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&[_]] = &[&[5], &[1,2,3]]; + assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&[_]] = &[&[], &[], &[], &[1,2]]; + assert_eq!(xs.rsplitn(3, |_| true).collect::>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.rsplitn(1, |x| *x == 5).collect::>(), splits); +} + +#[test] +fn test_windowsator() { + let v = &[1,2,3,4]; + + let wins: &[&[_]] = &[&[1,2], &[2,3], &[3,4]]; + assert_eq!(v.windows(2).collect::>(), wins); + + let wins: &[&[_]] = &[&[1,2,3], &[2,3,4]]; + assert_eq!(v.windows(3).collect::>(), wins); + assert!(v.windows(6).next().is_none()); + + let wins: &[&[_]] = &[&[3,4], &[2,3], &[1,2]]; + assert_eq!(v.windows(2).rev().collect::>(), wins); + let mut it = v.windows(2); + assert_eq!(it.indexable(), 3); + let win: &[_] = &[1,2]; + assert_eq!(it.idx(0).unwrap(), win); + let win: &[_] = &[2,3]; + assert_eq!(it.idx(1).unwrap(), win); + let win: &[_] = &[3,4]; + assert_eq!(it.idx(2).unwrap(), win); + assert_eq!(it.idx(3), None); +} + +#[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::>(), chunks); + let chunks: &[&[_]] = &[&[1,2,3], &[4,5]]; + assert_eq!(v.chunks(3).collect::>(), chunks); + let chunks: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(v.chunks(6).collect::>(), chunks); + + let chunks: &[&[_]] = &[&[5], &[3,4], &[1,2]]; + assert_eq!(v.chunks(2).rev().collect::>(), chunks); + let mut it = v.chunks(2); + assert_eq!(it.indexable(), 3); + + let chunk: &[_] = &[1,2]; + assert_eq!(it.idx(0).unwrap(), chunk); + let chunk: &[_] = &[3,4]; + assert_eq!(it.idx(1).unwrap(), chunk); + let chunk: &[_] = &[5]; + assert_eq!(it.idx(2).unwrap(), chunk); + assert_eq!(it.idx(3), None); +} + +#[test] +#[should_panic] +fn test_chunksator_0() { + let v = &[1,2,3,4]; + let _it = v.chunks(0); +} + +#[test] +fn test_move_from() { + let mut a = [1,2,3,4,5]; + let b = vec![6,7,8]; + assert_eq!(a.move_from(b, 0, 3), 3); + assert!(a == [6,7,8,4,5]); + let mut a = [7,2,8,1]; + let b = vec![3,1,4,1,5,9]; + assert_eq!(a.move_from(b, 0, 6), 4); + assert!(a == [3,1,4,1]); + let mut a = [1,2,3,4]; + let b = vec![5,6,7,8,9,0]; + assert_eq!(a.move_from(b, 2, 3), 1); + assert!(a == [7,2,3,4]); + let mut a = [1,2,3,4,5]; + let b = vec![5,6,7,8,9,0]; + assert_eq!(a[2..4].move_from(b,1,6), 2); + assert!(a == [1,2,6,7,5]); +} + +#[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::::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); +} + +#[test] +fn test_bytes_set_memory() { + use std::slice::bytes::MutableByteVector; + + let mut values = [1,2,3,4,5]; + values[0..5].set_memory(0xAB); + assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]); + values[2..4].set_memory(0xFF); + assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]); +} + +#[test] +#[should_panic] +fn test_overflow_does_not_cause_segfault() { + let mut v = vec![]; + v.reserve_exact(-1); + 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(-1); + v.push(Rc::new(2)); +} + +#[test] +fn test_mut_split_at() { + let mut values = [1u8,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::>()); +} + +#[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]); +} + +mod bench { + use std::iter::repeat; + use std::{mem, ptr}; + use std::rand::{Rng, weak_rng}; + + use test::{Bencher, black_box}; + + #[bench] + fn iterator(b: &mut Bencher) { + // peculiar numbers to stop LLVM from optimising the summation + // out. + let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect(); + + b.iter(|| { + let mut sum = 0; + for x in &v { + sum += *x; + } + // sum == 11806, to stop dead code elimination. + if sum == 0 {panic!()} + }) + } + + #[bench] + fn mut_iterator(b: &mut Bencher) { + let mut v: Vec<_> = repeat(0).take(100).collect(); + + b.iter(|| { + let mut i = 0; + for x in &mut v { + *x = i; + i += 1; + } + }) + } + + #[bench] + fn concat(b: &mut Bencher) { + let xss: Vec> = + (0..100).map(|i| (0..i).collect()).collect(); + b.iter(|| { + xss.concat(); + }); + } + + #[bench] + fn connect(b: &mut Bencher) { + let xss: Vec> = + (0..100).map(|i| (0..i).collect()).collect(); + b.iter(|| { + xss.connect(&0) + }); + } + + #[bench] + fn push(b: &mut Bencher) { + let mut vec = Vec::::new(); + b.iter(|| { + vec.push(0); + black_box(&vec); + }); + } + + #[bench] + fn starts_with_same_vector(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| { + vec.starts_with(&vec) + }) + } + + #[bench] + fn starts_with_single_element(b: &mut Bencher) { + let vec: Vec<_> = vec![0]; + b.iter(|| { + vec.starts_with(&vec) + }) + } + + #[bench] + fn starts_with_diff_one_element_at_end(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + let mut match_vec: Vec<_> = (0..99).collect(); + match_vec.push(0); + b.iter(|| { + vec.starts_with(&match_vec) + }) + } + + #[bench] + fn ends_with_same_vector(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| { + vec.ends_with(&vec) + }) + } + + #[bench] + fn ends_with_single_element(b: &mut Bencher) { + let vec: Vec<_> = vec![0]; + b.iter(|| { + vec.ends_with(&vec) + }) + } + + #[bench] + fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + let mut match_vec: Vec<_> = (0..100).collect(); + match_vec[0] = 200; + b.iter(|| { + vec.starts_with(&match_vec) + }) + } + + #[bench] + fn contains_last_element(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| { + vec.contains(&99) + }) + } + + #[bench] + fn zero_1kb_from_elem(b: &mut Bencher) { + b.iter(|| { + repeat(0u8).take(1024).collect::>() + }); + } + + #[bench] + fn zero_1kb_set_memory(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::::with_capacity(1024); + unsafe { + let vp = v.as_mut_ptr(); + ptr::set_memory(vp, 0, 1024); + v.set_len(1024); + } + v + }); + } + + #[bench] + fn zero_1kb_loop_set(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::::with_capacity(1024); + unsafe { + v.set_len(1024); + } + for i in 0..1024 { + v[i] = 0; + } + }); + } + + #[bench] + fn zero_1kb_mut_iter(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::::with_capacity(1024); + unsafe { + v.set_len(1024); + } + for x in &mut v { + *x = 0; + } + v + }); + } + + #[bench] + fn random_inserts(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = repeat((0, 0)).take(30).collect(); + for _ in 0..100 { + let l = v.len(); + v.insert(rng.gen::() % (l + 1), + (1, 1)); + } + }) + } + #[bench] + fn random_removes(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = repeat((0, 0)).take(130).collect(); + for _ in 0..100 { + let l = v.len(); + v.remove(rng.gen::() % l); + } + }) + } + + #[bench] + fn sort_random_small(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = rng.gen_iter::().take(5).collect(); + v.sort(); + }); + b.bytes = 5 * mem::size_of::() as u64; + } + + #[bench] + fn sort_random_medium(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = rng.gen_iter::().take(100).collect(); + v.sort(); + }); + b.bytes = 100 * mem::size_of::() as u64; + } + + #[bench] + fn sort_random_large(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = rng.gen_iter::().take(10000).collect(); + v.sort(); + }); + b.bytes = 10000 * mem::size_of::() as u64; + } + + #[bench] + fn sort_sorted(b: &mut Bencher) { + let mut v: Vec<_> = (0..10000).collect(); + b.iter(|| { + v.sort(); + }); + b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; + } + + type BigSortable = (u64, u64, u64, u64); + + #[bench] + fn sort_big_random_small(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v = rng.gen_iter::().take(5) + .collect::>(); + v.sort(); + }); + b.bytes = 5 * mem::size_of::() as u64; + } + + #[bench] + fn sort_big_random_medium(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v = rng.gen_iter::().take(100) + .collect::>(); + v.sort(); + }); + b.bytes = 100 * mem::size_of::() as u64; + } + + #[bench] + fn sort_big_random_large(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v = rng.gen_iter::().take(10000) + .collect::>(); + v.sort(); + }); + b.bytes = 10000 * mem::size_of::() as u64; + } + + #[bench] + fn sort_big_sorted(b: &mut Bencher) { + let mut v: Vec = (0..10000).map(|i| (i, i, i, i)).collect(); + b.iter(|| { + v.sort(); + }); + b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; + } +} diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs new file mode 100644 index 0000000000000..79c2d719862a9 --- /dev/null +++ b/src/libcollectionstest/str.rs @@ -0,0 +1,1668 @@ +// 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 or the MIT license +// , 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::iter::AdditiveIterator; +use std::str::{Utf8Error, from_utf8}; + +#[test] +fn test_le() { + assert!("" <= ""); + assert!("" <= "foo"); + assert!("foo" <= "foo"); + assert!("foo" != "bar"); +} + +#[test] +fn test_len() { + assert_eq!("".len(), 0); + assert_eq!("hello world".len(), 11); + assert_eq!("\x63".len(), 1); + assert_eq!("\u{a2}".len(), 2); + assert_eq!("\u{3c0}".len(), 2); + assert_eq!("\u{2620}".len(), 3); + assert_eq!("\u{1d11e}".len(), 4); + + assert_eq!("".chars().count(), 0); + assert_eq!("hello world".chars().count(), 11); + assert_eq!("\x63".chars().count(), 1); + assert_eq!("\u{a2}".chars().count(), 1); + assert_eq!("\u{3c0}".chars().count(), 1); + assert_eq!("\u{2620}".chars().count(), 1); + assert_eq!("\u{1d11e}".chars().count(), 1); + assert_eq!("ประเทศไทย中华Việt Nam".chars().count(), 19); + + assert_eq!("hello".width(false), 10); + assert_eq!("hello".width(true), 10); + assert_eq!("\0\0\0\0\0".width(false), 0); + assert_eq!("\0\0\0\0\0".width(true), 0); + assert_eq!("".width(false), 0); + assert_eq!("".width(true), 0); + assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(false), 4); + assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(true), 8); +} + +#[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 = String::from_str(""); + let s: String = empty.chars().collect(); + assert_eq!(empty, s); + let data = String::from_str("ประเทศไทย中"); + let s: String = data.chars().collect(); + assert_eq!(data, s); +} + +#[test] +fn test_into_bytes() { + let data = String::from_str("asdf"); + let buf = data.into_bytes(); + assert_eq!(b"asdf", buf); +} + +#[test] +fn test_find_str() { + // byte positions + assert_eq!("".find_str(""), Some(0)); + assert!("banana".find_str("apple pie").is_none()); + + let data = "abcabc"; + assert_eq!(data[0..6].find_str("ab"), Some(0)); + assert_eq!(data[2..6].find_str("ab"), Some(3 - 2)); + assert!(data[2..4].find_str("ab").is_none()); + + let string = "ประเทศไทย中华Việt Nam"; + let mut data = String::from_str(string); + data.push_str(string); + assert!(data.find_str("ไท华").is_none()); + assert_eq!(data[0..43].find_str(""), Some(0)); + assert_eq!(data[6..43].find_str(""), Some(6 - 6)); + + assert_eq!(data[0..43].find_str("ประ"), Some( 0)); + assert_eq!(data[0..43].find_str("ทศไ"), Some(12)); + assert_eq!(data[0..43].find_str("ย中"), Some(24)); + assert_eq!(data[0..43].find_str("iệt"), Some(34)); + assert_eq!(data[0..43].find_str("Nam"), Some(40)); + + assert_eq!(data[43..86].find_str("ประ"), Some(43 - 43)); + assert_eq!(data[43..86].find_str("ทศไ"), Some(55 - 43)); + assert_eq!(data[43..86].find_str("ย中"), Some(67 - 43)); + assert_eq!(data[43..86].find_str("iệt"), Some(77 - 43)); + assert_eq!(data[43..86].find_str("Nam"), Some(83 - 43)); +} + +#[test] +fn test_slice_chars() { + fn t(a: &str, b: &str, start: usize) { + assert_eq!(a.slice_chars(start, start + b.chars().count()), b); + } + t("", "", 0); + t("hello", "llo", 2); + t("hello", "el", 1); + t("αβλ", "β", 1); + t("αβλ", "", 3); + assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".slice_chars(2, 8)); +} + +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_concat!("ab", vec!["a", "b"]); + test_concat!("ab", vec![s("a"), s("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_connect { + ($expected: expr, $string: expr, $delim: expr) => { + { + let s = $string.connect($delim); + assert_eq!($expected, s); + } + } +} + +#[test] +fn test_connect_for_different_types() { + test_connect!("a-b", ["a", "b"], "-"); + let hyphen = "-".to_string(); + test_connect!("a-b", [s("a"), s("b")], &*hyphen); + test_connect!("a-b", vec!["a", "b"], &*hyphen); + test_connect!("a-b", &*vec!["a", "b"], "-"); + test_connect!("a-b", vec![s("a"), s("b")], "-"); +} + +#[test] +fn test_connect_for_different_lengths() { + let empty: &[&str] = &[]; + test_connect!("", empty, "-"); + test_connect!("a", ["a"], "-"); + test_connect!("a-b", ["a", "b"], "-"); + test_connect!("-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!(half_a_million_letter_a() == + unsafe {String::from_str(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_replace() { + let a = "a"; + assert_eq!("".replace(a, "b"), String::from_str("")); + assert_eq!("a".replace(a, "b"), String::from_str("b")); + assert_eq!("ab".replace(a, "b"), String::from_str("bb")); + let test = "test"; + assert!(" test test ".replace(test, "toast") == + String::from_str(" toast toast ")); + assert_eq!(" test test ".replace(test, ""), String::from_str(" ")); +} + +#[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_slice() { + assert_eq!("ab", "abc".slice(0, 2)); + assert_eq!("bc", "abc".slice(1, 3)); + assert_eq!("", "abc".slice(1, 1)); + assert_eq!("\u{65e5}", "\u{65e5}\u{672c}".slice(0, 3)); + + let data = "ประเทศไทย中华"; + assert_eq!("ป", data.slice(0, 3)); + assert_eq!("ร", data.slice(3, 6)); + assert_eq!("", data.slice(3, 3)); + assert_eq!("华", data.slice(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!(half_a_million_letter_x() == + String::from_str(letters.slice(0, 3 * 500000))); +} + +#[test] +fn test_slice_2() { + let ss = "中华Việt Nam"; + + assert_eq!("华", ss.slice(3, 6)); + assert_eq!("Việt Nam", ss.slice(6, 16)); + + assert_eq!("ab", "abc".slice(0, 2)); + assert_eq!("bc", "abc".slice(1, 3)); + assert_eq!("", "abc".slice(1, 1)); + + assert_eq!("中", ss.slice(0, 3)); + assert_eq!("华V", ss.slice(3, 7)); + assert_eq!("", ss.slice(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".slice(0, 2); +} + +#[test] +fn test_slice_from() { + assert_eq!("abcd".slice_from(0), "abcd"); + assert_eq!("abcd".slice_from(2), "cd"); + assert_eq!("abcd".slice_from(4), ""); +} +#[test] +fn test_slice_to() { + assert_eq!("abcd".slice_to(0), ""); + assert_eq!("abcd".slice_to(2), "ab"); + assert_eq!("abcd".slice_to(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_slice_shift_char() { + let data = "ประเทศไทย中"; + assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中"))); +} + +#[test] +fn test_slice_shift_char_2() { + let empty = ""; + assert_eq!(empty.slice_shift_char(), None); +} + +#[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 test_is_utf16() { + use unicode::str::is_utf16; + + macro_rules! pos { + ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } } + } + + // non-surrogates + pos!(&[0x0000], + &[0x0001, 0x0002], + &[0xD7FF], + &[0xE000]); + + // surrogate pairs (randomly generated with Python 3's + // .encode('utf-16be')) + pos!(&[0xdb54, 0xdf16, 0xd880, 0xdee0, 0xdb6a, 0xdd45], + &[0xd91f, 0xdeb1, 0xdb31, 0xdd84, 0xd8e2, 0xde14], + &[0xdb9f, 0xdc26, 0xdb6f, 0xde58, 0xd850, 0xdfae]); + + // mixtures (also random) + pos!(&[0xd921, 0xdcc2, 0x002d, 0x004d, 0xdb32, 0xdf65], + &[0xdb45, 0xdd2d, 0x006a, 0xdacd, 0xddfe, 0x0006], + &[0x0067, 0xd8ff, 0xddb7, 0x000f, 0xd900, 0xdc80]); + + // negative tests + macro_rules! neg { + ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } } + } + + neg!( + // surrogate + regular unit + &[0xdb45, 0x0000], + // surrogate + lead surrogate + &[0xd900, 0xd900], + // unterminated surrogate + &[0xd8ff], + // trail surrogate without a lead + &[0xddb7]); + + // random byte sequences that Python 3's .decode('utf-16be') + // failed on + neg!(&[0x5b3d, 0x0141, 0xde9e, 0x8fdc, 0xc6e7], + &[0xdf5a, 0x82a5, 0x62b9, 0xb447, 0x92f3], + &[0xda4e, 0x42bc, 0x4462, 0xee98, 0xc2ca], + &[0xbe00, 0xb04a, 0x6ecb, 0xdd89, 0xe278], + &[0x0465, 0xab56, 0xdbb6, 0xa893, 0x665e], + &[0x6b7f, 0x0a19, 0x40f4, 0xa657, 0xdcc5], + &[0x9b50, 0xda5e, 0x24ec, 0x03ad, 0x6dee], + &[0x8d17, 0xcaa7, 0xf4ae, 0xdf6e, 0xbed7], + &[0xdaee, 0x2584, 0x7d30, 0xa626, 0x121a], + &[0xd956, 0x4b43, 0x7570, 0xccd6, 0x4f4a], + &[0x9dcf, 0x1b49, 0x4ba5, 0xfce9, 0xdffe], + &[0x6572, 0xce53, 0xb05a, 0xf6af, 0xdacf], + &[0x1b90, 0x728c, 0x9906, 0xdb68, 0xf46e], + &[0x1606, 0xbeca, 0xbe76, 0x860f, 0xdfa5], + &[0x8b4f, 0xde7a, 0xd220, 0x9fac, 0x2b6f], + &[0xb8fe, 0xebbe, 0xda32, 0x1a5f, 0x8b8b], + &[0x934b, 0x8956, 0xc434, 0x1881, 0xddf7], + &[0x5a95, 0x13fc, 0xf116, 0xd89b, 0x93f9], + &[0xd640, 0x71f1, 0xdd7d, 0x77eb, 0x1cd8], + &[0x348b, 0xaef0, 0xdb2c, 0xebf1, 0x1282], + &[0x50d7, 0xd824, 0x5010, 0xb369, 0x22ea]); +} + +#[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_str(""); + 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 test_subslice_offset() { + let a = "kernelsprite"; + let b = &a[7..a.len()]; + let c = &a[0..a.len() - 6]; + assert_eq!(a.subslice_offset(b), 7); + assert_eq!(a.subslice_offset(c), 0); + + let string = "a\nb\nc"; + let lines: Vec<&str> = string.lines().collect(); + assert_eq!(string.subslice_offset(lines[0]), 0); + assert_eq!(string.subslice_offset(lines[1]), 2); + assert_eq!(string.subslice_offset(lines[2]), 4); +} + +#[test] +#[should_panic] +fn test_subslice_offset_2() { + let a = "alchemiter"; + let b = "cruxtruder"; + a.subslice_offset(b); +} + +#[test] +fn vec_str_conversions() { + let s1: String = String::from_str("All mimsy were the borogoves"); + + let v: Vec = s1.as_bytes().to_vec(); + let s2: String = String::from_str(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]; + debug!("{}", a); + debug!("{}", b); + 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_char('b')); + assert!("a".contains_char('a')); + assert!(!"abc".contains_char('d')); + assert!(!"".contains_char('a')); +} + +#[test] +fn test_char_at() { + let s = "ศไทย中华Việt Nam"; + let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = 0; + for ch in &v { + assert!(s.char_at(pos) == *ch); + pos += ch.to_string().len(); + } +} + +#[test] +fn test_char_at_reverse() { + let s = "ศไทย中华Việt Nam"; + let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = s.len(); + for ch in v.iter().rev() { + assert!(s.char_at_reverse(pos) == *ch); + pos -= ch.to_string().len(); + } +} + +#[test] +fn test_escape_unicode() { + assert_eq!("abc".escape_unicode(), + String::from_str("\\u{61}\\u{62}\\u{63}")); + assert_eq!("a c".escape_unicode(), + String::from_str("\\u{61}\\u{20}\\u{63}")); + assert_eq!("\r\n\t".escape_unicode(), + String::from_str("\\u{d}\\u{a}\\u{9}")); + assert_eq!("'\"\\".escape_unicode(), + String::from_str("\\u{27}\\u{22}\\u{5c}")); + assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), + String::from_str("\\u{0}\\u{1}\\u{fe}\\u{ff}")); + assert_eq!("\u{100}\u{ffff}".escape_unicode(), + String::from_str("\\u{100}\\u{ffff}")); + assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), + String::from_str("\\u{10000}\\u{10ffff}")); + assert_eq!("ab\u{fb00}".escape_unicode(), + String::from_str("\\u{61}\\u{62}\\u{fb00}")); + assert_eq!("\u{1d4ea}\r".escape_unicode(), + String::from_str("\\u{1d4ea}\\u{d}")); +} + +#[test] +fn test_escape_default() { + assert_eq!("abc".escape_default(), String::from_str("abc")); + assert_eq!("a c".escape_default(), String::from_str("a c")); + assert_eq!("\r\n\t".escape_default(), String::from_str("\\r\\n\\t")); + assert_eq!("'\"\\".escape_default(), String::from_str("\\'\\\"\\\\")); + assert_eq!("\u{100}\u{ffff}".escape_default(), + String::from_str("\\u{100}\\u{ffff}")); + assert_eq!("\u{10000}\u{10ffff}".escape_default(), + String::from_str("\\u{10000}\\u{10ffff}")); + assert_eq!("ab\u{fb00}".escape_default(), + String::from_str("ab\\u{fb00}")); + assert_eq!("\u{1d4ea}\r".escape_default(), + String::from_str("\\u{1d4ea}\\r")); +} + +#[test] +fn test_total_ord() { + "1234".cmp("123") == Greater; + "123".cmp("1234") == Less; + "1234".cmp("1234") == Equal; + "12345555".cmp("123456") == Less; + "22".cmp("1234") == Greater; +} + +#[test] +fn test_char_range_at() { + let data = "b¢€𤭢𤭢€¢b"; + assert_eq!('b', data.char_range_at(0).ch); + assert_eq!('¢', data.char_range_at(1).ch); + assert_eq!('€', data.char_range_at(3).ch); + assert_eq!('𤭢', data.char_range_at(6).ch); + assert_eq!('𤭢', data.char_range_at(10).ch); + assert_eq!('€', data.char_range_at(14).ch); + assert_eq!('¢', data.char_range_at(17).ch); + assert_eq!('b', data.char_range_at(19).ch); +} + +#[test] +fn test_char_range_at_reverse_underflow() { + assert_eq!("abc".char_range_at_reverse(0).next, 0); +} + +#[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()); +} + +#[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 len = c.encode_utf8(&mut bytes).unwrap_or(0); + let s = ::std::str::from_utf8(&bytes[..len]).unwrap(); + 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 len = c.encode_utf8(&mut bytes).unwrap_or(0); + let s = ::std::str::from_utf8(&bytes[..len]).unwrap(); + 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_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_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_splitn_char_iterator() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.splitn(3, ' ').collect(); + assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); + + let split: Vec<&str> = data.splitn(3, |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(3, 'ä').collect(); + assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); + + let split: Vec<&str> = data.splitn(3, |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_words() { + let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; + let words: Vec<&str> = data.words().collect(); + assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) +} + +#[test] +fn test_nfd_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfd_chars().collect::(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "d\u{307}\u{1c4}"); + t!("\u{2026}", "\u{2026}"); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); + t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); + t!("a\u{301}", "a\u{301}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); + t!("\u{ac1c}", "\u{1100}\u{1162}"); +} + +#[test] +fn test_nfkd_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfkd_chars().collect::(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "d\u{307}DZ\u{30c}"); + t!("\u{2026}", "..."); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); + t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); + t!("a\u{301}", "a\u{301}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); + t!("\u{ac1c}", "\u{1100}\u{1162}"); +} + +#[test] +fn test_nfc_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfc_chars().collect::(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "\u{1e0b}\u{1c4}"); + t!("\u{2026}", "\u{2026}"); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); + t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); + t!("a\u{301}", "\u{e1}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{d4db}"); + t!("\u{ac1c}", "\u{ac1c}"); + t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); +} + +#[test] +fn test_nfkc_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfkc_chars().collect::(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "\u{1e0b}D\u{17d}"); + t!("\u{2026}", "..."); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); + t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); + t!("a\u{301}", "\u{e1}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{d4db}"); + t!("\u{ac1c}", "\u{ac1c}"); + t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); +} + +#[test] +fn test_lines() { + let data = "\nMäry häd ä little lämb\n\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 = "\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_graphemes() { + use std::iter::order; + + // official Unicode test data + // from http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt + let test_same: [(_, &[_]); 325] = [ + ("\u{20}\u{20}", &["\u{20}", "\u{20}"]), + ("\u{20}\u{308}\u{20}", &["\u{20}\u{308}", "\u{20}"]), + ("\u{20}\u{D}", &["\u{20}", "\u{D}"]), + ("\u{20}\u{308}\u{D}", &["\u{20}\u{308}", "\u{D}"]), + ("\u{20}\u{A}", &["\u{20}", "\u{A}"]), + ("\u{20}\u{308}\u{A}", &["\u{20}\u{308}", "\u{A}"]), + ("\u{20}\u{1}", &["\u{20}", "\u{1}"]), + ("\u{20}\u{308}\u{1}", &["\u{20}\u{308}", "\u{1}"]), + ("\u{20}\u{300}", &["\u{20}\u{300}"]), + ("\u{20}\u{308}\u{300}", &["\u{20}\u{308}\u{300}"]), + ("\u{20}\u{1100}", &["\u{20}", "\u{1100}"]), + ("\u{20}\u{308}\u{1100}", &["\u{20}\u{308}", "\u{1100}"]), + ("\u{20}\u{1160}", &["\u{20}", "\u{1160}"]), + ("\u{20}\u{308}\u{1160}", &["\u{20}\u{308}", "\u{1160}"]), + ("\u{20}\u{11A8}", &["\u{20}", "\u{11A8}"]), + ("\u{20}\u{308}\u{11A8}", &["\u{20}\u{308}", "\u{11A8}"]), + ("\u{20}\u{AC00}", &["\u{20}", "\u{AC00}"]), + ("\u{20}\u{308}\u{AC00}", &["\u{20}\u{308}", "\u{AC00}"]), + ("\u{20}\u{AC01}", &["\u{20}", "\u{AC01}"]), + ("\u{20}\u{308}\u{AC01}", &["\u{20}\u{308}", "\u{AC01}"]), + ("\u{20}\u{1F1E6}", &["\u{20}", "\u{1F1E6}"]), + ("\u{20}\u{308}\u{1F1E6}", &["\u{20}\u{308}", "\u{1F1E6}"]), + ("\u{20}\u{378}", &["\u{20}", "\u{378}"]), + ("\u{20}\u{308}\u{378}", &["\u{20}\u{308}", "\u{378}"]), + ("\u{D}\u{20}", &["\u{D}", "\u{20}"]), + ("\u{D}\u{308}\u{20}", &["\u{D}", "\u{308}", "\u{20}"]), + ("\u{D}\u{D}", &["\u{D}", "\u{D}"]), + ("\u{D}\u{308}\u{D}", &["\u{D}", "\u{308}", "\u{D}"]), + ("\u{D}\u{A}", &["\u{D}\u{A}"]), + ("\u{D}\u{308}\u{A}", &["\u{D}", "\u{308}", "\u{A}"]), + ("\u{D}\u{1}", &["\u{D}", "\u{1}"]), + ("\u{D}\u{308}\u{1}", &["\u{D}", "\u{308}", "\u{1}"]), + ("\u{D}\u{300}", &["\u{D}", "\u{300}"]), + ("\u{D}\u{308}\u{300}", &["\u{D}", "\u{308}\u{300}"]), + ("\u{D}\u{903}", &["\u{D}", "\u{903}"]), + ("\u{D}\u{1100}", &["\u{D}", "\u{1100}"]), + ("\u{D}\u{308}\u{1100}", &["\u{D}", "\u{308}", "\u{1100}"]), + ("\u{D}\u{1160}", &["\u{D}", "\u{1160}"]), + ("\u{D}\u{308}\u{1160}", &["\u{D}", "\u{308}", "\u{1160}"]), + ("\u{D}\u{11A8}", &["\u{D}", "\u{11A8}"]), + ("\u{D}\u{308}\u{11A8}", &["\u{D}", "\u{308}", "\u{11A8}"]), + ("\u{D}\u{AC00}", &["\u{D}", "\u{AC00}"]), + ("\u{D}\u{308}\u{AC00}", &["\u{D}", "\u{308}", "\u{AC00}"]), + ("\u{D}\u{AC01}", &["\u{D}", "\u{AC01}"]), + ("\u{D}\u{308}\u{AC01}", &["\u{D}", "\u{308}", "\u{AC01}"]), + ("\u{D}\u{1F1E6}", &["\u{D}", "\u{1F1E6}"]), + ("\u{D}\u{308}\u{1F1E6}", &["\u{D}", "\u{308}", "\u{1F1E6}"]), + ("\u{D}\u{378}", &["\u{D}", "\u{378}"]), + ("\u{D}\u{308}\u{378}", &["\u{D}", "\u{308}", "\u{378}"]), + ("\u{A}\u{20}", &["\u{A}", "\u{20}"]), + ("\u{A}\u{308}\u{20}", &["\u{A}", "\u{308}", "\u{20}"]), + ("\u{A}\u{D}", &["\u{A}", "\u{D}"]), + ("\u{A}\u{308}\u{D}", &["\u{A}", "\u{308}", "\u{D}"]), + ("\u{A}\u{A}", &["\u{A}", "\u{A}"]), + ("\u{A}\u{308}\u{A}", &["\u{A}", "\u{308}", "\u{A}"]), + ("\u{A}\u{1}", &["\u{A}", "\u{1}"]), + ("\u{A}\u{308}\u{1}", &["\u{A}", "\u{308}", "\u{1}"]), + ("\u{A}\u{300}", &["\u{A}", "\u{300}"]), + ("\u{A}\u{308}\u{300}", &["\u{A}", "\u{308}\u{300}"]), + ("\u{A}\u{903}", &["\u{A}", "\u{903}"]), + ("\u{A}\u{1100}", &["\u{A}", "\u{1100}"]), + ("\u{A}\u{308}\u{1100}", &["\u{A}", "\u{308}", "\u{1100}"]), + ("\u{A}\u{1160}", &["\u{A}", "\u{1160}"]), + ("\u{A}\u{308}\u{1160}", &["\u{A}", "\u{308}", "\u{1160}"]), + ("\u{A}\u{11A8}", &["\u{A}", "\u{11A8}"]), + ("\u{A}\u{308}\u{11A8}", &["\u{A}", "\u{308}", "\u{11A8}"]), + ("\u{A}\u{AC00}", &["\u{A}", "\u{AC00}"]), + ("\u{A}\u{308}\u{AC00}", &["\u{A}", "\u{308}", "\u{AC00}"]), + ("\u{A}\u{AC01}", &["\u{A}", "\u{AC01}"]), + ("\u{A}\u{308}\u{AC01}", &["\u{A}", "\u{308}", "\u{AC01}"]), + ("\u{A}\u{1F1E6}", &["\u{A}", "\u{1F1E6}"]), + ("\u{A}\u{308}\u{1F1E6}", &["\u{A}", "\u{308}", "\u{1F1E6}"]), + ("\u{A}\u{378}", &["\u{A}", "\u{378}"]), + ("\u{A}\u{308}\u{378}", &["\u{A}", "\u{308}", "\u{378}"]), + ("\u{1}\u{20}", &["\u{1}", "\u{20}"]), + ("\u{1}\u{308}\u{20}", &["\u{1}", "\u{308}", "\u{20}"]), + ("\u{1}\u{D}", &["\u{1}", "\u{D}"]), + ("\u{1}\u{308}\u{D}", &["\u{1}", "\u{308}", "\u{D}"]), + ("\u{1}\u{A}", &["\u{1}", "\u{A}"]), + ("\u{1}\u{308}\u{A}", &["\u{1}", "\u{308}", "\u{A}"]), + ("\u{1}\u{1}", &["\u{1}", "\u{1}"]), + ("\u{1}\u{308}\u{1}", &["\u{1}", "\u{308}", "\u{1}"]), + ("\u{1}\u{300}", &["\u{1}", "\u{300}"]), + ("\u{1}\u{308}\u{300}", &["\u{1}", "\u{308}\u{300}"]), + ("\u{1}\u{903}", &["\u{1}", "\u{903}"]), + ("\u{1}\u{1100}", &["\u{1}", "\u{1100}"]), + ("\u{1}\u{308}\u{1100}", &["\u{1}", "\u{308}", "\u{1100}"]), + ("\u{1}\u{1160}", &["\u{1}", "\u{1160}"]), + ("\u{1}\u{308}\u{1160}", &["\u{1}", "\u{308}", "\u{1160}"]), + ("\u{1}\u{11A8}", &["\u{1}", "\u{11A8}"]), + ("\u{1}\u{308}\u{11A8}", &["\u{1}", "\u{308}", "\u{11A8}"]), + ("\u{1}\u{AC00}", &["\u{1}", "\u{AC00}"]), + ("\u{1}\u{308}\u{AC00}", &["\u{1}", "\u{308}", "\u{AC00}"]), + ("\u{1}\u{AC01}", &["\u{1}", "\u{AC01}"]), + ("\u{1}\u{308}\u{AC01}", &["\u{1}", "\u{308}", "\u{AC01}"]), + ("\u{1}\u{1F1E6}", &["\u{1}", "\u{1F1E6}"]), + ("\u{1}\u{308}\u{1F1E6}", &["\u{1}", "\u{308}", "\u{1F1E6}"]), + ("\u{1}\u{378}", &["\u{1}", "\u{378}"]), + ("\u{1}\u{308}\u{378}", &["\u{1}", "\u{308}", "\u{378}"]), + ("\u{300}\u{20}", &["\u{300}", "\u{20}"]), + ("\u{300}\u{308}\u{20}", &["\u{300}\u{308}", "\u{20}"]), + ("\u{300}\u{D}", &["\u{300}", "\u{D}"]), + ("\u{300}\u{308}\u{D}", &["\u{300}\u{308}", "\u{D}"]), + ("\u{300}\u{A}", &["\u{300}", "\u{A}"]), + ("\u{300}\u{308}\u{A}", &["\u{300}\u{308}", "\u{A}"]), + ("\u{300}\u{1}", &["\u{300}", "\u{1}"]), + ("\u{300}\u{308}\u{1}", &["\u{300}\u{308}", "\u{1}"]), + ("\u{300}\u{300}", &["\u{300}\u{300}"]), + ("\u{300}\u{308}\u{300}", &["\u{300}\u{308}\u{300}"]), + ("\u{300}\u{1100}", &["\u{300}", "\u{1100}"]), + ("\u{300}\u{308}\u{1100}", &["\u{300}\u{308}", "\u{1100}"]), + ("\u{300}\u{1160}", &["\u{300}", "\u{1160}"]), + ("\u{300}\u{308}\u{1160}", &["\u{300}\u{308}", "\u{1160}"]), + ("\u{300}\u{11A8}", &["\u{300}", "\u{11A8}"]), + ("\u{300}\u{308}\u{11A8}", &["\u{300}\u{308}", "\u{11A8}"]), + ("\u{300}\u{AC00}", &["\u{300}", "\u{AC00}"]), + ("\u{300}\u{308}\u{AC00}", &["\u{300}\u{308}", "\u{AC00}"]), + ("\u{300}\u{AC01}", &["\u{300}", "\u{AC01}"]), + ("\u{300}\u{308}\u{AC01}", &["\u{300}\u{308}", "\u{AC01}"]), + ("\u{300}\u{1F1E6}", &["\u{300}", "\u{1F1E6}"]), + ("\u{300}\u{308}\u{1F1E6}", &["\u{300}\u{308}", "\u{1F1E6}"]), + ("\u{300}\u{378}", &["\u{300}", "\u{378}"]), + ("\u{300}\u{308}\u{378}", &["\u{300}\u{308}", "\u{378}"]), + ("\u{903}\u{20}", &["\u{903}", "\u{20}"]), + ("\u{903}\u{308}\u{20}", &["\u{903}\u{308}", "\u{20}"]), + ("\u{903}\u{D}", &["\u{903}", "\u{D}"]), + ("\u{903}\u{308}\u{D}", &["\u{903}\u{308}", "\u{D}"]), + ("\u{903}\u{A}", &["\u{903}", "\u{A}"]), + ("\u{903}\u{308}\u{A}", &["\u{903}\u{308}", "\u{A}"]), + ("\u{903}\u{1}", &["\u{903}", "\u{1}"]), + ("\u{903}\u{308}\u{1}", &["\u{903}\u{308}", "\u{1}"]), + ("\u{903}\u{300}", &["\u{903}\u{300}"]), + ("\u{903}\u{308}\u{300}", &["\u{903}\u{308}\u{300}"]), + ("\u{903}\u{1100}", &["\u{903}", "\u{1100}"]), + ("\u{903}\u{308}\u{1100}", &["\u{903}\u{308}", "\u{1100}"]), + ("\u{903}\u{1160}", &["\u{903}", "\u{1160}"]), + ("\u{903}\u{308}\u{1160}", &["\u{903}\u{308}", "\u{1160}"]), + ("\u{903}\u{11A8}", &["\u{903}", "\u{11A8}"]), + ("\u{903}\u{308}\u{11A8}", &["\u{903}\u{308}", "\u{11A8}"]), + ("\u{903}\u{AC00}", &["\u{903}", "\u{AC00}"]), + ("\u{903}\u{308}\u{AC00}", &["\u{903}\u{308}", "\u{AC00}"]), + ("\u{903}\u{AC01}", &["\u{903}", "\u{AC01}"]), + ("\u{903}\u{308}\u{AC01}", &["\u{903}\u{308}", "\u{AC01}"]), + ("\u{903}\u{1F1E6}", &["\u{903}", "\u{1F1E6}"]), + ("\u{903}\u{308}\u{1F1E6}", &["\u{903}\u{308}", "\u{1F1E6}"]), + ("\u{903}\u{378}", &["\u{903}", "\u{378}"]), + ("\u{903}\u{308}\u{378}", &["\u{903}\u{308}", "\u{378}"]), + ("\u{1100}\u{20}", &["\u{1100}", "\u{20}"]), + ("\u{1100}\u{308}\u{20}", &["\u{1100}\u{308}", "\u{20}"]), + ("\u{1100}\u{D}", &["\u{1100}", "\u{D}"]), + ("\u{1100}\u{308}\u{D}", &["\u{1100}\u{308}", "\u{D}"]), + ("\u{1100}\u{A}", &["\u{1100}", "\u{A}"]), + ("\u{1100}\u{308}\u{A}", &["\u{1100}\u{308}", "\u{A}"]), + ("\u{1100}\u{1}", &["\u{1100}", "\u{1}"]), + ("\u{1100}\u{308}\u{1}", &["\u{1100}\u{308}", "\u{1}"]), + ("\u{1100}\u{300}", &["\u{1100}\u{300}"]), + ("\u{1100}\u{308}\u{300}", &["\u{1100}\u{308}\u{300}"]), + ("\u{1100}\u{1100}", &["\u{1100}\u{1100}"]), + ("\u{1100}\u{308}\u{1100}", &["\u{1100}\u{308}", "\u{1100}"]), + ("\u{1100}\u{1160}", &["\u{1100}\u{1160}"]), + ("\u{1100}\u{308}\u{1160}", &["\u{1100}\u{308}", "\u{1160}"]), + ("\u{1100}\u{11A8}", &["\u{1100}", "\u{11A8}"]), + ("\u{1100}\u{308}\u{11A8}", &["\u{1100}\u{308}", "\u{11A8}"]), + ("\u{1100}\u{AC00}", &["\u{1100}\u{AC00}"]), + ("\u{1100}\u{308}\u{AC00}", &["\u{1100}\u{308}", "\u{AC00}"]), + ("\u{1100}\u{AC01}", &["\u{1100}\u{AC01}"]), + ("\u{1100}\u{308}\u{AC01}", &["\u{1100}\u{308}", "\u{AC01}"]), + ("\u{1100}\u{1F1E6}", &["\u{1100}", "\u{1F1E6}"]), + ("\u{1100}\u{308}\u{1F1E6}", &["\u{1100}\u{308}", "\u{1F1E6}"]), + ("\u{1100}\u{378}", &["\u{1100}", "\u{378}"]), + ("\u{1100}\u{308}\u{378}", &["\u{1100}\u{308}", "\u{378}"]), + ("\u{1160}\u{20}", &["\u{1160}", "\u{20}"]), + ("\u{1160}\u{308}\u{20}", &["\u{1160}\u{308}", "\u{20}"]), + ("\u{1160}\u{D}", &["\u{1160}", "\u{D}"]), + ("\u{1160}\u{308}\u{D}", &["\u{1160}\u{308}", "\u{D}"]), + ("\u{1160}\u{A}", &["\u{1160}", "\u{A}"]), + ("\u{1160}\u{308}\u{A}", &["\u{1160}\u{308}", "\u{A}"]), + ("\u{1160}\u{1}", &["\u{1160}", "\u{1}"]), + ("\u{1160}\u{308}\u{1}", &["\u{1160}\u{308}", "\u{1}"]), + ("\u{1160}\u{300}", &["\u{1160}\u{300}"]), + ("\u{1160}\u{308}\u{300}", &["\u{1160}\u{308}\u{300}"]), + ("\u{1160}\u{1100}", &["\u{1160}", "\u{1100}"]), + ("\u{1160}\u{308}\u{1100}", &["\u{1160}\u{308}", "\u{1100}"]), + ("\u{1160}\u{1160}", &["\u{1160}\u{1160}"]), + ("\u{1160}\u{308}\u{1160}", &["\u{1160}\u{308}", "\u{1160}"]), + ("\u{1160}\u{11A8}", &["\u{1160}\u{11A8}"]), + ("\u{1160}\u{308}\u{11A8}", &["\u{1160}\u{308}", "\u{11A8}"]), + ("\u{1160}\u{AC00}", &["\u{1160}", "\u{AC00}"]), + ("\u{1160}\u{308}\u{AC00}", &["\u{1160}\u{308}", "\u{AC00}"]), + ("\u{1160}\u{AC01}", &["\u{1160}", "\u{AC01}"]), + ("\u{1160}\u{308}\u{AC01}", &["\u{1160}\u{308}", "\u{AC01}"]), + ("\u{1160}\u{1F1E6}", &["\u{1160}", "\u{1F1E6}"]), + ("\u{1160}\u{308}\u{1F1E6}", &["\u{1160}\u{308}", "\u{1F1E6}"]), + ("\u{1160}\u{378}", &["\u{1160}", "\u{378}"]), + ("\u{1160}\u{308}\u{378}", &["\u{1160}\u{308}", "\u{378}"]), + ("\u{11A8}\u{20}", &["\u{11A8}", "\u{20}"]), + ("\u{11A8}\u{308}\u{20}", &["\u{11A8}\u{308}", "\u{20}"]), + ("\u{11A8}\u{D}", &["\u{11A8}", "\u{D}"]), + ("\u{11A8}\u{308}\u{D}", &["\u{11A8}\u{308}", "\u{D}"]), + ("\u{11A8}\u{A}", &["\u{11A8}", "\u{A}"]), + ("\u{11A8}\u{308}\u{A}", &["\u{11A8}\u{308}", "\u{A}"]), + ("\u{11A8}\u{1}", &["\u{11A8}", "\u{1}"]), + ("\u{11A8}\u{308}\u{1}", &["\u{11A8}\u{308}", "\u{1}"]), + ("\u{11A8}\u{300}", &["\u{11A8}\u{300}"]), + ("\u{11A8}\u{308}\u{300}", &["\u{11A8}\u{308}\u{300}"]), + ("\u{11A8}\u{1100}", &["\u{11A8}", "\u{1100}"]), + ("\u{11A8}\u{308}\u{1100}", &["\u{11A8}\u{308}", "\u{1100}"]), + ("\u{11A8}\u{1160}", &["\u{11A8}", "\u{1160}"]), + ("\u{11A8}\u{308}\u{1160}", &["\u{11A8}\u{308}", "\u{1160}"]), + ("\u{11A8}\u{11A8}", &["\u{11A8}\u{11A8}"]), + ("\u{11A8}\u{308}\u{11A8}", &["\u{11A8}\u{308}", "\u{11A8}"]), + ("\u{11A8}\u{AC00}", &["\u{11A8}", "\u{AC00}"]), + ("\u{11A8}\u{308}\u{AC00}", &["\u{11A8}\u{308}", "\u{AC00}"]), + ("\u{11A8}\u{AC01}", &["\u{11A8}", "\u{AC01}"]), + ("\u{11A8}\u{308}\u{AC01}", &["\u{11A8}\u{308}", "\u{AC01}"]), + ("\u{11A8}\u{1F1E6}", &["\u{11A8}", "\u{1F1E6}"]), + ("\u{11A8}\u{308}\u{1F1E6}", &["\u{11A8}\u{308}", "\u{1F1E6}"]), + ("\u{11A8}\u{378}", &["\u{11A8}", "\u{378}"]), + ("\u{11A8}\u{308}\u{378}", &["\u{11A8}\u{308}", "\u{378}"]), + ("\u{AC00}\u{20}", &["\u{AC00}", "\u{20}"]), + ("\u{AC00}\u{308}\u{20}", &["\u{AC00}\u{308}", "\u{20}"]), + ("\u{AC00}\u{D}", &["\u{AC00}", "\u{D}"]), + ("\u{AC00}\u{308}\u{D}", &["\u{AC00}\u{308}", "\u{D}"]), + ("\u{AC00}\u{A}", &["\u{AC00}", "\u{A}"]), + ("\u{AC00}\u{308}\u{A}", &["\u{AC00}\u{308}", "\u{A}"]), + ("\u{AC00}\u{1}", &["\u{AC00}", "\u{1}"]), + ("\u{AC00}\u{308}\u{1}", &["\u{AC00}\u{308}", "\u{1}"]), + ("\u{AC00}\u{300}", &["\u{AC00}\u{300}"]), + ("\u{AC00}\u{308}\u{300}", &["\u{AC00}\u{308}\u{300}"]), + ("\u{AC00}\u{1100}", &["\u{AC00}", "\u{1100}"]), + ("\u{AC00}\u{308}\u{1100}", &["\u{AC00}\u{308}", "\u{1100}"]), + ("\u{AC00}\u{1160}", &["\u{AC00}\u{1160}"]), + ("\u{AC00}\u{308}\u{1160}", &["\u{AC00}\u{308}", "\u{1160}"]), + ("\u{AC00}\u{11A8}", &["\u{AC00}\u{11A8}"]), + ("\u{AC00}\u{308}\u{11A8}", &["\u{AC00}\u{308}", "\u{11A8}"]), + ("\u{AC00}\u{AC00}", &["\u{AC00}", "\u{AC00}"]), + ("\u{AC00}\u{308}\u{AC00}", &["\u{AC00}\u{308}", "\u{AC00}"]), + ("\u{AC00}\u{AC01}", &["\u{AC00}", "\u{AC01}"]), + ("\u{AC00}\u{308}\u{AC01}", &["\u{AC00}\u{308}", "\u{AC01}"]), + ("\u{AC00}\u{1F1E6}", &["\u{AC00}", "\u{1F1E6}"]), + ("\u{AC00}\u{308}\u{1F1E6}", &["\u{AC00}\u{308}", "\u{1F1E6}"]), + ("\u{AC00}\u{378}", &["\u{AC00}", "\u{378}"]), + ("\u{AC00}\u{308}\u{378}", &["\u{AC00}\u{308}", "\u{378}"]), + ("\u{AC01}\u{20}", &["\u{AC01}", "\u{20}"]), + ("\u{AC01}\u{308}\u{20}", &["\u{AC01}\u{308}", "\u{20}"]), + ("\u{AC01}\u{D}", &["\u{AC01}", "\u{D}"]), + ("\u{AC01}\u{308}\u{D}", &["\u{AC01}\u{308}", "\u{D}"]), + ("\u{AC01}\u{A}", &["\u{AC01}", "\u{A}"]), + ("\u{AC01}\u{308}\u{A}", &["\u{AC01}\u{308}", "\u{A}"]), + ("\u{AC01}\u{1}", &["\u{AC01}", "\u{1}"]), + ("\u{AC01}\u{308}\u{1}", &["\u{AC01}\u{308}", "\u{1}"]), + ("\u{AC01}\u{300}", &["\u{AC01}\u{300}"]), + ("\u{AC01}\u{308}\u{300}", &["\u{AC01}\u{308}\u{300}"]), + ("\u{AC01}\u{1100}", &["\u{AC01}", "\u{1100}"]), + ("\u{AC01}\u{308}\u{1100}", &["\u{AC01}\u{308}", "\u{1100}"]), + ("\u{AC01}\u{1160}", &["\u{AC01}", "\u{1160}"]), + ("\u{AC01}\u{308}\u{1160}", &["\u{AC01}\u{308}", "\u{1160}"]), + ("\u{AC01}\u{11A8}", &["\u{AC01}\u{11A8}"]), + ("\u{AC01}\u{308}\u{11A8}", &["\u{AC01}\u{308}", "\u{11A8}"]), + ("\u{AC01}\u{AC00}", &["\u{AC01}", "\u{AC00}"]), + ("\u{AC01}\u{308}\u{AC00}", &["\u{AC01}\u{308}", "\u{AC00}"]), + ("\u{AC01}\u{AC01}", &["\u{AC01}", "\u{AC01}"]), + ("\u{AC01}\u{308}\u{AC01}", &["\u{AC01}\u{308}", "\u{AC01}"]), + ("\u{AC01}\u{1F1E6}", &["\u{AC01}", "\u{1F1E6}"]), + ("\u{AC01}\u{308}\u{1F1E6}", &["\u{AC01}\u{308}", "\u{1F1E6}"]), + ("\u{AC01}\u{378}", &["\u{AC01}", "\u{378}"]), + ("\u{AC01}\u{308}\u{378}", &["\u{AC01}\u{308}", "\u{378}"]), + ("\u{1F1E6}\u{20}", &["\u{1F1E6}", "\u{20}"]), + ("\u{1F1E6}\u{308}\u{20}", &["\u{1F1E6}\u{308}", "\u{20}"]), + ("\u{1F1E6}\u{D}", &["\u{1F1E6}", "\u{D}"]), + ("\u{1F1E6}\u{308}\u{D}", &["\u{1F1E6}\u{308}", "\u{D}"]), + ("\u{1F1E6}\u{A}", &["\u{1F1E6}", "\u{A}"]), + ("\u{1F1E6}\u{308}\u{A}", &["\u{1F1E6}\u{308}", "\u{A}"]), + ("\u{1F1E6}\u{1}", &["\u{1F1E6}", "\u{1}"]), + ("\u{1F1E6}\u{308}\u{1}", &["\u{1F1E6}\u{308}", "\u{1}"]), + ("\u{1F1E6}\u{300}", &["\u{1F1E6}\u{300}"]), + ("\u{1F1E6}\u{308}\u{300}", &["\u{1F1E6}\u{308}\u{300}"]), + ("\u{1F1E6}\u{1100}", &["\u{1F1E6}", "\u{1100}"]), + ("\u{1F1E6}\u{308}\u{1100}", &["\u{1F1E6}\u{308}", "\u{1100}"]), + ("\u{1F1E6}\u{1160}", &["\u{1F1E6}", "\u{1160}"]), + ("\u{1F1E6}\u{308}\u{1160}", &["\u{1F1E6}\u{308}", "\u{1160}"]), + ("\u{1F1E6}\u{11A8}", &["\u{1F1E6}", "\u{11A8}"]), + ("\u{1F1E6}\u{308}\u{11A8}", &["\u{1F1E6}\u{308}", "\u{11A8}"]), + ("\u{1F1E6}\u{AC00}", &["\u{1F1E6}", "\u{AC00}"]), + ("\u{1F1E6}\u{308}\u{AC00}", &["\u{1F1E6}\u{308}", "\u{AC00}"]), + ("\u{1F1E6}\u{AC01}", &["\u{1F1E6}", "\u{AC01}"]), + ("\u{1F1E6}\u{308}\u{AC01}", &["\u{1F1E6}\u{308}", "\u{AC01}"]), + ("\u{1F1E6}\u{1F1E6}", &["\u{1F1E6}\u{1F1E6}"]), + ("\u{1F1E6}\u{308}\u{1F1E6}", &["\u{1F1E6}\u{308}", "\u{1F1E6}"]), + ("\u{1F1E6}\u{378}", &["\u{1F1E6}", "\u{378}"]), + ("\u{1F1E6}\u{308}\u{378}", &["\u{1F1E6}\u{308}", "\u{378}"]), + ("\u{378}\u{20}", &["\u{378}", "\u{20}"]), + ("\u{378}\u{308}\u{20}", &["\u{378}\u{308}", "\u{20}"]), + ("\u{378}\u{D}", &["\u{378}", "\u{D}"]), + ("\u{378}\u{308}\u{D}", &["\u{378}\u{308}", "\u{D}"]), + ("\u{378}\u{A}", &["\u{378}", "\u{A}"]), + ("\u{378}\u{308}\u{A}", &["\u{378}\u{308}", "\u{A}"]), + ("\u{378}\u{1}", &["\u{378}", "\u{1}"]), + ("\u{378}\u{308}\u{1}", &["\u{378}\u{308}", "\u{1}"]), + ("\u{378}\u{300}", &["\u{378}\u{300}"]), + ("\u{378}\u{308}\u{300}", &["\u{378}\u{308}\u{300}"]), + ("\u{378}\u{1100}", &["\u{378}", "\u{1100}"]), + ("\u{378}\u{308}\u{1100}", &["\u{378}\u{308}", "\u{1100}"]), + ("\u{378}\u{1160}", &["\u{378}", "\u{1160}"]), + ("\u{378}\u{308}\u{1160}", &["\u{378}\u{308}", "\u{1160}"]), + ("\u{378}\u{11A8}", &["\u{378}", "\u{11A8}"]), + ("\u{378}\u{308}\u{11A8}", &["\u{378}\u{308}", "\u{11A8}"]), + ("\u{378}\u{AC00}", &["\u{378}", "\u{AC00}"]), + ("\u{378}\u{308}\u{AC00}", &["\u{378}\u{308}", "\u{AC00}"]), + ("\u{378}\u{AC01}", &["\u{378}", "\u{AC01}"]), + ("\u{378}\u{308}\u{AC01}", &["\u{378}\u{308}", "\u{AC01}"]), + ("\u{378}\u{1F1E6}", &["\u{378}", "\u{1F1E6}"]), + ("\u{378}\u{308}\u{1F1E6}", &["\u{378}\u{308}", "\u{1F1E6}"]), + ("\u{378}\u{378}", &["\u{378}", "\u{378}"]), + ("\u{378}\u{308}\u{378}", &["\u{378}\u{308}", "\u{378}"]), + ("\u{61}\u{1F1E6}\u{62}", &["\u{61}", "\u{1F1E6}", "\u{62}"]), + ("\u{1F1F7}\u{1F1FA}", &["\u{1F1F7}\u{1F1FA}"]), + ("\u{1F1F7}\u{1F1FA}\u{1F1F8}", &["\u{1F1F7}\u{1F1FA}\u{1F1F8}"]), + ("\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}", + &["\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}"]), + ("\u{1F1F7}\u{1F1FA}\u{200B}\u{1F1F8}\u{1F1EA}", + &["\u{1F1F7}\u{1F1FA}", "\u{200B}", "\u{1F1F8}\u{1F1EA}"]), + ("\u{1F1E6}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{1F1E7}\u{1F1E8}"]), + ("\u{1F1E6}\u{200D}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{200D}", + "\u{1F1E7}\u{1F1E8}"]), + ("\u{1F1E6}\u{1F1E7}\u{200D}\u{1F1E8}", + &["\u{1F1E6}\u{1F1E7}\u{200D}", "\u{1F1E8}"]), + ("\u{20}\u{200D}\u{646}", &["\u{20}\u{200D}", "\u{646}"]), + ("\u{646}\u{200D}\u{20}", &["\u{646}\u{200D}", "\u{20}"]), + ]; + + let test_diff: [(_, &[_], &[_]); 23] = [ + ("\u{20}\u{903}", &["\u{20}\u{903}"], &["\u{20}", "\u{903}"]), ("\u{20}\u{308}\u{903}", + &["\u{20}\u{308}\u{903}"], &["\u{20}\u{308}", "\u{903}"]), ("\u{D}\u{308}\u{903}", + &["\u{D}", "\u{308}\u{903}"], &["\u{D}", "\u{308}", "\u{903}"]), ("\u{A}\u{308}\u{903}", + &["\u{A}", "\u{308}\u{903}"], &["\u{A}", "\u{308}", "\u{903}"]), ("\u{1}\u{308}\u{903}", + &["\u{1}", "\u{308}\u{903}"], &["\u{1}", "\u{308}", "\u{903}"]), ("\u{300}\u{903}", + &["\u{300}\u{903}"], &["\u{300}", "\u{903}"]), ("\u{300}\u{308}\u{903}", + &["\u{300}\u{308}\u{903}"], &["\u{300}\u{308}", "\u{903}"]), ("\u{903}\u{903}", + &["\u{903}\u{903}"], &["\u{903}", "\u{903}"]), ("\u{903}\u{308}\u{903}", + &["\u{903}\u{308}\u{903}"], &["\u{903}\u{308}", "\u{903}"]), ("\u{1100}\u{903}", + &["\u{1100}\u{903}"], &["\u{1100}", "\u{903}"]), ("\u{1100}\u{308}\u{903}", + &["\u{1100}\u{308}\u{903}"], &["\u{1100}\u{308}", "\u{903}"]), ("\u{1160}\u{903}", + &["\u{1160}\u{903}"], &["\u{1160}", "\u{903}"]), ("\u{1160}\u{308}\u{903}", + &["\u{1160}\u{308}\u{903}"], &["\u{1160}\u{308}", "\u{903}"]), ("\u{11A8}\u{903}", + &["\u{11A8}\u{903}"], &["\u{11A8}", "\u{903}"]), ("\u{11A8}\u{308}\u{903}", + &["\u{11A8}\u{308}\u{903}"], &["\u{11A8}\u{308}", "\u{903}"]), ("\u{AC00}\u{903}", + &["\u{AC00}\u{903}"], &["\u{AC00}", "\u{903}"]), ("\u{AC00}\u{308}\u{903}", + &["\u{AC00}\u{308}\u{903}"], &["\u{AC00}\u{308}", "\u{903}"]), ("\u{AC01}\u{903}", + &["\u{AC01}\u{903}"], &["\u{AC01}", "\u{903}"]), ("\u{AC01}\u{308}\u{903}", + &["\u{AC01}\u{308}\u{903}"], &["\u{AC01}\u{308}", "\u{903}"]), ("\u{1F1E6}\u{903}", + &["\u{1F1E6}\u{903}"], &["\u{1F1E6}", "\u{903}"]), ("\u{1F1E6}\u{308}\u{903}", + &["\u{1F1E6}\u{308}\u{903}"], &["\u{1F1E6}\u{308}", "\u{903}"]), ("\u{378}\u{903}", + &["\u{378}\u{903}"], &["\u{378}", "\u{903}"]), ("\u{378}\u{308}\u{903}", + &["\u{378}\u{308}\u{903}"], &["\u{378}\u{308}", "\u{903}"]), + ]; + + for &(s, g) in &test_same[..] { + // test forward iterator + assert!(order::equals(s.graphemes(true), g.iter().cloned())); + assert!(order::equals(s.graphemes(false), g.iter().cloned())); + + // test reverse iterator + assert!(order::equals(s.graphemes(true).rev(), g.iter().rev().cloned())); + assert!(order::equals(s.graphemes(false).rev(), g.iter().rev().cloned())); + } + + for &(s, gt, gf) in &test_diff { + // test forward iterator + assert!(order::equals(s.graphemes(true), gt.iter().cloned())); + assert!(order::equals(s.graphemes(false), gf.iter().cloned())); + + // test reverse iterator + assert!(order::equals(s.graphemes(true).rev(), gt.iter().rev().cloned())); + assert!(order::equals(s.graphemes(false).rev(), gf.iter().rev().cloned())); + } + + // test the indices iterators + let s = "a̐éö̲\r\n"; + let gr_inds = s.grapheme_indices(true).collect::>(); + let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; + assert_eq!(gr_inds, b); + let gr_inds = s.grapheme_indices(true).rev().collect::>(); + let b: &[_] = &[(11, "\r\n"), (6, "ö̲"), (3, "é"), (0, "a̐")]; + assert_eq!(gr_inds, b); + let mut gr_inds_iter = s.grapheme_indices(true); + { + let gr_inds = gr_inds_iter.by_ref(); + let e1 = gr_inds.size_hint(); + assert_eq!(e1, (1, Some(13))); + let c = gr_inds.count(); + assert_eq!(c, 4); + } + let e2 = gr_inds_iter.size_hint(); + assert_eq!(e2, (0, Some(0))); + + // make sure the reverse iterator does the right thing with "\n" at beginning of string + let s = "\n\r\n\r"; + let gr = s.graphemes(true).rev().collect::>(); + let b: &[_] = &["\r", "\r\n", "\n"]; + assert_eq!(gr, b); +} + +#[test] +fn test_split_strator() { + fn t(s: &str, sep: &str, u: &[&str]) { + let v: Vec<&str> = s.split_str(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() { + let s: S = Default::default(); + assert_eq!(s.as_slice(), ""); + } + + t::<&str>(); + t::(); +} + +#[test] +fn test_str_container() { + fn sum_len(v: &[&str]) -> usize { + v.iter().map(|x| x.len()).sum() + } + + let s = String::from_str("01234"); + assert_eq!(5, sum_len(&["012", "", "34"])); + assert_eq!(5, sum_len(&[&String::from_str("01"), + &String::from_str("2"), + &String::from_str("34"), + &String::from_str("")])); + 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_eq!(from_utf8(xs), Err(Utf8Error::TooShort)); +} + +mod bench { + use test::{Bencher, black_box}; + + #[bench] + fn char_iterator(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| s.chars().count()); + } + + #[bench] + fn char_iterator_for(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| { + for ch in s.chars() { black_box(ch); } + }); + } + + #[bench] + fn char_iterator_ascii(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb"; + + b.iter(|| s.chars().count()); + } + + #[bench] + fn char_iterator_rev(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| s.chars().rev().count()); + } + + #[bench] + fn char_iterator_rev_for(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| { + for ch in s.chars().rev() { black_box(ch); } + }); + } + + #[bench] + fn char_indicesator(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let len = s.chars().count(); + + b.iter(|| assert_eq!(s.char_indices().count(), len)); + } + + #[bench] + fn char_indicesator_rev(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let len = s.chars().count(); + + b.iter(|| assert_eq!(s.char_indices().rev().count(), len)); + } + + #[bench] + fn split_unicode_ascii(b: &mut Bencher) { + let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; + + b.iter(|| assert_eq!(s.split('V').count(), 3)); + } + + #[bench] + fn split_ascii(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + b.iter(|| assert_eq!(s.split(' ').count(), len)); + } + + #[bench] + fn split_extern_fn(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + fn pred(c: char) -> bool { c == ' ' } + + b.iter(|| assert_eq!(s.split(pred).count(), len)); + } + + #[bench] + fn split_closure(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len)); + } + + #[bench] + fn split_slice(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + let c: &[char] = &[' ']; + b.iter(|| assert_eq!(s.split(c).count(), len)); + } + + #[bench] + fn bench_connect(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let sep = "→"; + let v = vec![s, s, s, s, s, s, s, s, s, s]; + b.iter(|| { + assert_eq!(v.connect(sep).len(), s.len() * 10 + sep.len() * 9); + }) + } + + #[bench] + fn bench_contains_short_short(b: &mut Bencher) { + let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + let needle = "sit"; + + b.iter(|| { + assert!(haystack.contains(needle)); + }) + } + + #[bench] + fn bench_contains_short_long(b: &mut Bencher) { + let haystack = "\ +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. + +In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ +sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ +diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ +lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ +eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ +interdum. Curabitur ut nisi justo. + +Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ +mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ +lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ +est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ +felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ +ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ +feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ +Aliquam sit amet placerat lorem. + +Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ +mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ +Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ +lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ +suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ +cursus accumsan. + +Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ +feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ +vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ +leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ +malesuada sollicitudin quam eu fermentum."; + let needle = "english"; + + b.iter(|| { + assert!(!haystack.contains(needle)); + }) + } + + #[bench] + fn bench_contains_bad_naive(b: &mut Bencher) { + let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + let needle = "aaaaaaaab"; + + b.iter(|| { + assert!(!haystack.contains(needle)); + }) + } + + #[bench] + fn bench_contains_equal(b: &mut Bencher) { + let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + + b.iter(|| { + assert!(haystack.contains(needle)); + }) + } +} diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs new file mode 100644 index 0000000000000..4768d5e92ac30 --- /dev/null +++ b/src/libcollectionstest/string.rs @@ -0,0 +1,453 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::IntoCow; +use std::iter::repeat; +use std::str::Utf8Error; +use std::string::{CowString, as_string}; + +use test::Bencher; + +#[test] +fn test_as_string() { + let x = "foo"; + assert_eq!(x, &**as_string(x)); +} + +#[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_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_str("hello")); + + let xs = "ศไทย中华Việt Nam".as_bytes().to_vec(); + assert_eq!(String::from_utf8(xs).unwrap(), + String::from_str("ศไทย中华Việt Nam")); + + let xs = b"hello\xFF".to_vec(); + let err = String::from_utf8(xs).err().unwrap(); + assert_eq!(err.utf8_error(), Utf8Error::TooShort); + assert_eq!(err.into_bytes(), b"hello\xff".to_vec()); +} + +#[test] +fn test_from_utf8_lossy() { + let xs = b"hello"; + let ys: CowString = "hello".into_cow(); + assert_eq!(String::from_utf8_lossy(xs), ys); + + let xs = "ศไทย中华Việt Nam".as_bytes(); + let ys: CowString = "ศไทย中华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_str("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_str("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_str("\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_str("\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_str("\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_str("\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_str("\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_str("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"), + vec![0xd800, 0xdf45, 0xd800, 0xdf3f, + 0xd800, 0xdf3b, 0xd800, 0xdf46, + 0xd800, 0xdf39, 0xd800, 0xdf3b, + 0xd800, 0xdf30, 0x000a]), + + (String::from_str("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"), + vec![0xd801, 0xdc12, 0xd801, + 0xdc49, 0xd801, 0xdc2e, 0xd801, + 0xdc40, 0xd801, 0xdc32, 0xd801, + 0xdc4b, 0x0020, 0xd801, 0xdc0f, + 0xd801, 0xdc32, 0xd801, 0xdc4d, + 0x000a]), + + (String::from_str("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\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_str("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\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_str("\u{20000}"), + vec![0xD840, 0xDC00])]; + + for p in &pairs { + let (s, u) = (*p).clone(); + let s_as_utf16 = s.utf16_units().collect::>(); + let u_as_string = String::from_utf16(&u).unwrap(); + + assert!(::unicode::str::is_utf16(&u)); + 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.utf16_units().collect::>(), 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_str("\u{FFFD}")); + // lead + lead + assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), + String::from_str("\u{FFFD}\u{FFFD}")); + + // isolated trail + assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from_str("a\u{FFFD}")); + + // general + assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]), + String::from_str("\u{FFFD}𐒋\u{FFFD}")); +} + +#[test] +fn test_push_bytes() { + let mut s = String::from_str("ABC"); + unsafe { + let mv = s.as_mut_vec(); + mv.push_all(&[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_push() { + let mut data = String::from_str("ประเทศไทย中"); + 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_str("ประเทศไทย中华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_str_truncate() { + let mut s = String::from_str("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_str("12345"); + let p = s.as_ptr(); + s.truncate(3); + s.push_str("6"); + let p_ = s.as_ptr(); + assert_eq!(p_, p); +} + +#[test] +#[should_panic] +fn test_str_truncate_invalid_len() { + let mut s = String::from_str("12345"); + s.truncate(6); +} + +#[test] +#[should_panic] +fn test_str_truncate_split_codepoint() { + let mut s = String::from_str("\u{FC}"); // ü + s.truncate(1); +} + +#[test] +fn test_str_clear() { + let mut s = String::from_str("12345"); + s.clear(); + assert_eq!(s.len(), 0); + assert_eq!(s, ""); +} + +#[test] +fn test_str_add() { + let a = String::from_str("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 = 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].into_iter()); + assert_eq!(s, d); +} + +#[bench] +fn bench_with_capacity(b: &mut Bencher) { + b.iter(|| { + String::with_capacity(100) + }); +} + +#[bench] +fn bench_push_str(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + b.iter(|| { + let mut r = String::new(); + r.push_str(s); + }); +} + +const REPETITIONS: u64 = 10_000; + +#[bench] +fn bench_push_str_one_byte(b: &mut Bencher) { + b.bytes = REPETITIONS; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push_str("a") + } + }); +} + +#[bench] +fn bench_push_char_one_byte(b: &mut Bencher) { + b.bytes = REPETITIONS; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push('a') + } + }); +} + +#[bench] +fn bench_push_char_two_bytes(b: &mut Bencher) { + b.bytes = REPETITIONS * 2; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push('â') + } + }); +} + +#[bench] +fn from_utf8_lossy_100_ascii(b: &mut Bencher) { + let s = b"Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; + + assert_eq!(100, s.len()); + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_100_multibyte(b: &mut Bencher) { + let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); + assert_eq!(100, s.len()); + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_invalid(b: &mut Bencher) { + let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_100_invalid(b: &mut Bencher) { + let s = repeat(0xf5).take(100).collect::>(); + b.iter(|| { + let _ = String::from_utf8_lossy(&s); + }); +} + +#[bench] +fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { + let s = "Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; + // ensure our operation produces an exact-size string before we benchmark it + let mut r = String::with_capacity(s.len()); + r.push_str(s); + assert_eq!(r.len(), r.capacity()); + b.iter(|| { + let mut r = String::with_capacity(s.len()); + r.push_str(s); + r.shrink_to_fit(); + r + }); +} diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs new file mode 100644 index 0000000000000..2923bea982845 --- /dev/null +++ b/src/libcollectionstest/vec.rs @@ -0,0 +1,994 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::iter::{FromIterator, repeat}; +use std::mem::size_of; +use std::vec::as_vec; + +use test::Bencher; + +struct DropCounter<'a> { + count: &'a mut u32 +} + +#[unsafe_destructor] +impl<'a> Drop for DropCounter<'a> { + fn drop(&mut self) { + *self.count += 1; + } +} + +#[test] +fn test_as_vec() { + let xs = [1u8, 2u8, 3u8]; + assert_eq!(&**as_vec(&xs), xs); +} + +#[test] +fn test_as_vec_dtor() { + let (mut count_x, mut count_y) = (0, 0); + { + let xs = &[DropCounter { count: &mut count_x }, DropCounter { count: &mut count_y }]; + assert_eq!(as_vec(xs).len(), 2); + } + assert_eq!(count_x, 1); + assert_eq!(count_y, 1); +} + +#[test] +fn test_small_vec_struct() { + assert!(size_of::>() == size_of::() * 3); +} + +#[test] +fn test_double_drop() { + struct TwoVec { + x: Vec, + y: Vec + } + + 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); +} + +#[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 = 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> = vec!(box 1, box 2, box 3); + let two: Vec> = 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 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_unsafe_ptrs() { + unsafe { + // Test on-stack copy-from-buf. + let a = [1, 2, 3]; + let ptr = a.as_ptr(); + let b = Vec::from_raw_buf(ptr, 3); + assert_eq!(b, [1, 2, 3]); + + // Test on-heap copy-from-buf. + let c = vec![1, 2, 3, 4, 5]; + let ptr = c.as_ptr(); + let d = Vec::from_raw_buf(ptr, 5); + assert_eq!(d, [1, 2, 3, 4, 5]); + } +} + +#[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[-1..]; +} + +#[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[-1..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::::new(); + vec.swap_remove(0); +} + +#[test] +fn test_move_iter_unwrap() { + let mut vec = Vec::with_capacity(7); + vec.push(1); + vec.push(2); + let ptr = vec.as_ptr(); + vec = vec.into_iter().into_inner(); + assert_eq!(vec.as_ptr(), ptr); + assert_eq!(vec.capacity(), 7); + assert_eq!(vec.len(), 0); +} + +#[test] +#[should_panic] +fn test_map_in_place_incompatible_types_fail() { + let v = vec![0, 1, 2]; + v.map_in_place(|_| ()); +} + +#[test] +fn test_map_in_place() { + let v = vec![0, 1, 2]; + assert_eq!(v.map_in_place(|i: u32| i as i32 - 1), [-1, 0, 1]); +} + +#[test] +fn test_map_in_place_zero_sized() { + let v = vec![(), ()]; + #[derive(PartialEq, Debug)] + struct ZeroSized; + assert_eq!(v.map_in_place(|_| ZeroSized), [ZeroSized, ZeroSized]); +} + +#[test] +fn test_map_in_place_zero_drop_count() { + use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; + + #[derive(Clone, PartialEq, Debug)] + struct Nothing; + impl Drop for Nothing { fn drop(&mut self) { } } + + #[derive(Clone, PartialEq, Debug)] + struct ZeroSized; + impl Drop for ZeroSized { + fn drop(&mut self) { + DROP_COUNTER.fetch_add(1, Ordering::Relaxed); + } + } + const NUM_ELEMENTS: usize = 2; + static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; + + let v = repeat(Nothing).take(NUM_ELEMENTS).collect::>(); + + DROP_COUNTER.store(0, Ordering::Relaxed); + + let v = v.map_in_place(|_| ZeroSized); + assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), 0); + drop(v); + assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), NUM_ELEMENTS); +} + +#[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] +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]); +} + +#[bench] +fn bench_new(b: &mut Bencher) { + b.iter(|| { + let v: Vec = Vec::new(); + assert_eq!(v.len(), 0); + assert_eq!(v.capacity(), 0); + }) +} + +fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| { + let v: Vec = Vec::with_capacity(src_len); + assert_eq!(v.len(), 0); + assert_eq!(v.capacity(), src_len); + }) +} + +#[bench] +fn bench_with_capacity_0000(b: &mut Bencher) { + do_bench_with_capacity(b, 0) +} + +#[bench] +fn bench_with_capacity_0010(b: &mut Bencher) { + do_bench_with_capacity(b, 10) +} + +#[bench] +fn bench_with_capacity_0100(b: &mut Bencher) { + do_bench_with_capacity(b, 100) +} + +#[bench] +fn bench_with_capacity_1000(b: &mut Bencher) { + do_bench_with_capacity(b, 1000) +} + +fn do_bench_from_fn(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| { + let dst = (0..src_len).collect::>(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }) +} + +#[bench] +fn bench_from_fn_0000(b: &mut Bencher) { + do_bench_from_fn(b, 0) +} + +#[bench] +fn bench_from_fn_0010(b: &mut Bencher) { + do_bench_from_fn(b, 10) +} + +#[bench] +fn bench_from_fn_0100(b: &mut Bencher) { + do_bench_from_fn(b, 100) +} + +#[bench] +fn bench_from_fn_1000(b: &mut Bencher) { + do_bench_from_fn(b, 1000) +} + +fn do_bench_from_elem(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| { + let dst: Vec = repeat(5).take(src_len).collect(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().all(|x| *x == 5)); + }) +} + +#[bench] +fn bench_from_elem_0000(b: &mut Bencher) { + do_bench_from_elem(b, 0) +} + +#[bench] +fn bench_from_elem_0010(b: &mut Bencher) { + do_bench_from_elem(b, 10) +} + +#[bench] +fn bench_from_elem_0100(b: &mut Bencher) { + do_bench_from_elem(b, 100) +} + +#[bench] +fn bench_from_elem_1000(b: &mut Bencher) { + do_bench_from_elem(b, 1000) +} + +fn do_bench_from_slice(b: &mut Bencher, src_len: usize) { + let src: Vec<_> = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let dst = src.clone()[..].to_vec(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_from_slice_0000(b: &mut Bencher) { + do_bench_from_slice(b, 0) +} + +#[bench] +fn bench_from_slice_0010(b: &mut Bencher) { + do_bench_from_slice(b, 10) +} + +#[bench] +fn bench_from_slice_0100(b: &mut Bencher) { + do_bench_from_slice(b, 100) +} + +#[bench] +fn bench_from_slice_1000(b: &mut Bencher) { + do_bench_from_slice(b, 1000) +} + +fn do_bench_from_iter(b: &mut Bencher, src_len: usize) { + let src: Vec<_> = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let dst: Vec<_> = FromIterator::from_iter(src.clone().into_iter()); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_from_iter_0000(b: &mut Bencher) { + do_bench_from_iter(b, 0) +} + +#[bench] +fn bench_from_iter_0010(b: &mut Bencher) { + do_bench_from_iter(b, 10) +} + +#[bench] +fn bench_from_iter_0100(b: &mut Bencher) { + do_bench_from_iter(b, 100) +} + +#[bench] +fn bench_from_iter_1000(b: &mut Bencher) { + do_bench_from_iter(b, 1000) +} + +fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..dst_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let mut dst = dst.clone(); + dst.extend(src.clone().into_iter()); + assert_eq!(dst.len(), dst_len + src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_extend_0000_0000(b: &mut Bencher) { + do_bench_extend(b, 0, 0) +} + +#[bench] +fn bench_extend_0000_0010(b: &mut Bencher) { + do_bench_extend(b, 0, 10) +} + +#[bench] +fn bench_extend_0000_0100(b: &mut Bencher) { + do_bench_extend(b, 0, 100) +} + +#[bench] +fn bench_extend_0000_1000(b: &mut Bencher) { + do_bench_extend(b, 0, 1000) +} + +#[bench] +fn bench_extend_0010_0010(b: &mut Bencher) { + do_bench_extend(b, 10, 10) +} + +#[bench] +fn bench_extend_0100_0100(b: &mut Bencher) { + do_bench_extend(b, 100, 100) +} + +#[bench] +fn bench_extend_1000_1000(b: &mut Bencher) { + do_bench_extend(b, 1000, 1000) +} + +fn do_bench_push_all(b: &mut Bencher, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..dst_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let mut dst = dst.clone(); + dst.push_all(&src); + assert_eq!(dst.len(), dst_len + src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_push_all_0000_0000(b: &mut Bencher) { + do_bench_push_all(b, 0, 0) +} + +#[bench] +fn bench_push_all_0000_0010(b: &mut Bencher) { + do_bench_push_all(b, 0, 10) +} + +#[bench] +fn bench_push_all_0000_0100(b: &mut Bencher) { + do_bench_push_all(b, 0, 100) +} + +#[bench] +fn bench_push_all_0000_1000(b: &mut Bencher) { + do_bench_push_all(b, 0, 1000) +} + +#[bench] +fn bench_push_all_0010_0010(b: &mut Bencher) { + do_bench_push_all(b, 10, 10) +} + +#[bench] +fn bench_push_all_0100_0100(b: &mut Bencher) { + do_bench_push_all(b, 100, 100) +} + +#[bench] +fn bench_push_all_1000_1000(b: &mut Bencher) { + do_bench_push_all(b, 1000, 1000) +} + +fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..dst_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let mut dst = dst.clone(); + dst.extend(src.clone().into_iter()); + assert_eq!(dst.len(), dst_len + src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_push_all_move_0000_0000(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 0) +} + +#[bench] +fn bench_push_all_move_0000_0010(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 10) +} + +#[bench] +fn bench_push_all_move_0000_0100(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 100) +} + +#[bench] +fn bench_push_all_move_0000_1000(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 1000) +} + +#[bench] +fn bench_push_all_move_0010_0010(b: &mut Bencher) { + do_bench_push_all_move(b, 10, 10) +} + +#[bench] +fn bench_push_all_move_0100_0100(b: &mut Bencher) { + do_bench_push_all_move(b, 100, 100) +} + +#[bench] +fn bench_push_all_move_1000_1000(b: &mut Bencher) { + do_bench_push_all_move(b, 1000, 1000) +} + +fn do_bench_clone(b: &mut Bencher, src_len: usize) { + let src: Vec = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let dst = src.clone(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_clone_0000(b: &mut Bencher) { + do_bench_clone(b, 0) +} + +#[bench] +fn bench_clone_0010(b: &mut Bencher) { + do_bench_clone(b, 10) +} + +#[bench] +fn bench_clone_0100(b: &mut Bencher) { + do_bench_clone(b, 100) +} + +#[bench] +fn bench_clone_1000(b: &mut Bencher) { + do_bench_clone(b, 1000) +} + +fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..src_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = (times * src_len) as u64; + + b.iter(|| { + let mut dst = dst.clone(); + + for _ in 0..times { + dst.clone_from(&src); + + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x)); + } + }); +} + +#[bench] +fn bench_clone_from_01_0000_0000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 0) +} + +#[bench] +fn bench_clone_from_01_0000_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 10) +} + +#[bench] +fn bench_clone_from_01_0000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 100) +} + +#[bench] +fn bench_clone_from_01_0000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 10) +} + +#[bench] +fn bench_clone_from_01_0100_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 100) +} + +#[bench] +fn bench_clone_from_01_1000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 1000, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 100) +} + +#[bench] +fn bench_clone_from_01_0100_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 0) +} + +#[bench] +fn bench_clone_from_01_0100_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 10) +} + +#[bench] +fn bench_clone_from_01_1000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 1000, 100) +} + +#[bench] +fn bench_clone_from_10_0000_0000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 0) +} + +#[bench] +fn bench_clone_from_10_0000_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 10) +} + +#[bench] +fn bench_clone_from_10_0000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 100) +} + +#[bench] +fn bench_clone_from_10_0000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 10) +} + +#[bench] +fn bench_clone_from_10_0100_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 100) +} + +#[bench] +fn bench_clone_from_10_1000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 1000, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 100) +} + +#[bench] +fn bench_clone_from_10_0100_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 0) +} + +#[bench] +fn bench_clone_from_10_0100_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 10) +} + +#[bench] +fn bench_clone_from_10_1000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 1000, 100) +} diff --git a/src/libcollectionstest/vec_deque.rs b/src/libcollectionstest/vec_deque.rs new file mode 100644 index 0000000000000..ba2ed36de2110 --- /dev/null +++ b/src/libcollectionstest/vec_deque.rs @@ -0,0 +1,1150 @@ +// 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 or the MIT license +// , 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::hash::{SipHasher, self}; + +use test; + +use self::Taggy::*; +use self::Taggypar::*; + +#[test] +#[allow(deprecated)] +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); + debug!("{}", d[0]); + debug!("{}", d[1]); + debug!("{}", d[2]); + debug!("{}", d[3]); + 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(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]; +} + +#[bench] +fn bench_new(b: &mut test::Bencher) { + b.iter(|| { + let ring: VecDeque = VecDeque::new(); + test::black_box(ring); + }) +} + +// FIXME(japaric) privacy +/* +#[bench] +fn bench_push_back_100(b: &mut test::Bencher) { + let mut deq = VecDeque::with_capacity(101); + b.iter(|| { + for i in 0..100 { + deq.push_back(i); + } + deq.head = 0; + deq.tail = 0; + }) +} +*/ + +// FIXME(japaric) privacy +/* +#[bench] +fn bench_push_front_100(b: &mut test::Bencher) { + let mut deq = VecDeque::with_capacity(101); + b.iter(|| { + for i in 0..100 { + deq.push_front(i); + } + deq.head = 0; + deq.tail = 0; + }) +} +*/ + +// FIXME(japaric) privacy +/* +#[bench] +fn bench_pop_back_100(b: &mut test::Bencher) { + let mut deq= VecDeque::::with_capacity(101); + + b.iter(|| { + deq.head = 100; + deq.tail = 0; + while !deq.is_empty() { + test::black_box(deq.pop_back()); + } + }) +} +*/ + +// FIXME(japaric) privacy +/* +#[bench] +fn bench_pop_front_100(b: &mut test::Bencher) { + let mut deq = VecDeque::::with_capacity(101); + + b.iter(|| { + deq.head = 100; + deq.tail = 0; + while !deq.is_empty() { + test::black_box(deq.pop_front()); + } + }) +} +*/ + +#[bench] +fn bench_grow_1025(b: &mut test::Bencher) { + b.iter(|| { + let mut deq = VecDeque::new(); + for i in 0..1025 { + deq.push_front(i); + } + test::black_box(deq); + }) +} + +#[bench] +fn bench_iter_1000(b: &mut test::Bencher) { + let ring: VecDeque<_> = (0..1000).collect(); + + b.iter(|| { + let mut sum = 0; + for &i in &ring { + sum += i; + } + test::black_box(sum); + }) +} + +#[bench] +fn bench_mut_iter_1000(b: &mut test::Bencher) { + let mut ring: VecDeque<_> = (0..1000).collect(); + + b.iter(|| { + let mut sum = 0; + for i in &mut ring { + sum += *i; + } + test::black_box(sum); + }) +} + +#[derive(Clone, PartialEq, Debug)] +enum Taggy { + One(i32), + Two(i32, i32), + Three(i32, i32, i32), +} + +#[derive(Clone, PartialEq, Debug)] +enum Taggypar { + 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::(5, 72, 64, 175); +} + +#[test] +fn test_param_taggy() { + test_parameterized::(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); +} + +#[test] +fn test_param_taggypar() { + test_parameterized::>(Onepar::(1), + Twopar::(1, 2), + Threepar::(1, 2, 3), + Twopar::(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::(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::>(), [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::>(), 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::>(), 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::>(), 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::>(), 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().cloned().collect::>(), + 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 = 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::>(), 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::>(), 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 = 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::>(), [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::>(), [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() { + use std::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 = iter::count(0, 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_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::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); +} + +#[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); +} + +// FIXME(japaric) privacy +/* +#[test] +fn test_swap_front_back_remove() { + fn test(back: bool) { + // This test checks that every single combination of tail position and length is tested. + // Capacity 15 should be large enough to cover every case. + let mut tester = VecDeque::with_capacity(15); + let usable_cap = tester.capacity(); + let final_len = usable_cap / 2; + + for len in 0..final_len { + let expected = if back { + (0..len).collect() + } else { + (0..len).rev().collect() + }; + for tail_pos in 0..usable_cap { + tester.tail = tail_pos; + tester.head = tail_pos; + if back { + for i in 0..len * 2 { + tester.push_front(i); + } + for i in 0..len { + assert_eq!(tester.swap_back_remove(i), Some(len * 2 - 1 - i)); + } + } else { + for i in 0..len * 2 { + tester.push_back(i); + } + for i in 0..len { + let idx = tester.len() - 1 - i; + assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i)); + } + } + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert_eq!(tester, expected); + } + } + } + test(true); + test(false); +} +*/ + +// FIXME(japaric) privacy +/* +#[test] +fn test_insert() { + // This test checks that every single combination of tail position, length, and + // insertion position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + + // len is the length *after* insertion + for len in 1..cap { + // 0, 1, 2, .., len - 1 + let expected = iter::count(0, 1).take(len).collect(); + for tail_pos in 0..cap { + for to_insert in 0..len { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + if i != to_insert { + tester.push_back(i); + } + } + tester.insert(to_insert, to_insert); + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert_eq!(tester, expected); + } + } + } +} +*/ + +// FIXME(japaric) privacy +/* +#[test] +fn test_remove() { + // This test checks that every single combination of tail position, length, and + // removal position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *after* removal + for len in 0..cap - 1 { + // 0, 1, 2, .., len - 1 + let expected = iter::count(0, 1).take(len).collect(); + for tail_pos in 0..cap { + for to_remove in 0..len + 1 { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + if i == to_remove { + tester.push_back(1234); + } + tester.push_back(i); + } + if to_remove == len { + tester.push_back(1234); + } + tester.remove(to_remove); + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert_eq!(tester, expected); + } + } + } +} +*/ + +// FIXME(japaric) privacy +/* +#[test] +fn test_shrink_to_fit() { + // This test checks that every single combination of head and tail position, + // is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + tester.reserve(63); + let max_cap = tester.capacity(); + + for len in 0..cap + 1 { + // 0, 1, 2, .., len - 1 + let expected = iter::count(0, 1).take(len).collect(); + for tail_pos in 0..max_cap + 1 { + tester.tail = tail_pos; + tester.head = tail_pos; + tester.reserve(63); + for i in 0..len { + tester.push_back(i); + } + tester.shrink_to_fit(); + assert!(tester.capacity() <= cap); + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert_eq!(tester, expected); + } + } +} +*/ + +#[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 = 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 = 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); +} + +// FIXME(japaric) privacy +/* +#[test] +fn test_split_off() { + // This test checks that every single combination of tail position, length, and + // split position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *before* splitting + for len in 0..cap { + // index to split at + for at in 0..len + 1 { + // 0, 1, 2, .., at - 1 (may be empty) + let expected_self = iter::count(0, 1).take(at).collect(); + // at, at + 1, .., len - 1 (may be empty) + let expected_other = iter::count(at, 1).take(len - at).collect(); + + for tail_pos in 0..cap { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + tester.push_back(i); + } + let result = tester.split_off(at); + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert!(result.tail < result.cap); + assert!(result.head < result.cap); + assert_eq!(tester, expected_self); + assert_eq!(result, expected_other); + } + } + } +} +*/ + +#[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::>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(b.iter().cloned().collect::>(), []); + + // append nothing to something + a.append(&mut b); + assert_eq!(a.iter().cloned().collect::>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(b.iter().cloned().collect::>(), []); + + // append something to nothing + b.append(&mut a); + assert_eq!(b.iter().cloned().collect::>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(a.iter().cloned().collect::>(), []); +} diff --git a/src/libcollectionstest/vec_map.rs b/src/libcollectionstest/vec_map.rs new file mode 100644 index 0000000000000..112b4c03e20e5 --- /dev/null +++ b/src/libcollectionstest/vec_map.rs @@ -0,0 +1,510 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::VecMap; +use std::collections::vec_map::Entry::{Occupied, Vacant}; +use std::hash::{SipHasher, hash}; + +#[test] +fn test_get_mut() { + let mut m = VecMap::new(); + assert!(m.insert(1, 12).is_none()); + assert!(m.insert(2, 8).is_none()); + assert!(m.insert(5, 14).is_none()); + let new = 100; + match m.get_mut(&5) { + None => panic!(), Some(x) => *x = new + } + assert_eq!(m.get(&5), Some(&new)); +} + +#[test] +fn test_len() { + let mut map = VecMap::new(); + assert_eq!(map.len(), 0); + assert!(map.is_empty()); + assert!(map.insert(5, 20).is_none()); + assert_eq!(map.len(), 1); + assert!(!map.is_empty()); + assert!(map.insert(11, 12).is_none()); + assert_eq!(map.len(), 2); + assert!(!map.is_empty()); + assert!(map.insert(14, 22).is_none()); + assert_eq!(map.len(), 3); + assert!(!map.is_empty()); +} + +#[test] +fn test_clear() { + let mut map = VecMap::new(); + assert!(map.insert(5, 20).is_none()); + assert!(map.insert(11, 12).is_none()); + assert!(map.insert(14, 22).is_none()); + map.clear(); + assert!(map.is_empty()); + assert!(map.get(&5).is_none()); + assert!(map.get(&11).is_none()); + assert!(map.get(&14).is_none()); +} + +#[test] +fn test_insert() { + let mut m = VecMap::new(); + assert_eq!(m.insert(1, 2), None); + assert_eq!(m.insert(1, 3), Some(2)); + assert_eq!(m.insert(1, 4), Some(3)); +} + +#[test] +fn test_remove() { + let mut m = VecMap::new(); + m.insert(1, 2); + assert_eq!(m.remove(&1), Some(2)); + assert_eq!(m.remove(&1), None); +} + +#[test] +fn test_keys() { + let mut map = VecMap::new(); + map.insert(1, 'a'); + map.insert(2, 'b'); + map.insert(3, 'c'); + let keys: Vec<_> = map.keys().collect(); + assert_eq!(keys.len(), 3); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&3)); +} + +#[test] +fn test_values() { + let mut map = VecMap::new(); + map.insert(1, 'a'); + map.insert(2, 'b'); + map.insert(3, 'c'); + let values: Vec<_> = map.values().cloned().collect(); + assert_eq!(values.len(), 3); + assert!(values.contains(&'a')); + assert!(values.contains(&'b')); + assert!(values.contains(&'c')); +} + +#[test] +fn test_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + let mut it = m.iter(); + assert_eq!(it.size_hint(), (0, Some(11))); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.size_hint(), (0, Some(10))); + assert_eq!(it.next().unwrap(), (1, &2)); + assert_eq!(it.size_hint(), (0, Some(9))); + assert_eq!(it.next().unwrap(), (3, &5)); + assert_eq!(it.size_hint(), (0, Some(7))); + assert_eq!(it.next().unwrap(), (6, &10)); + assert_eq!(it.size_hint(), (0, Some(4))); + assert_eq!(it.next().unwrap(), (10, &11)); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_iterator_size_hints() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + assert_eq!(m.iter().size_hint(), (0, Some(11))); + assert_eq!(m.iter().rev().size_hint(), (0, Some(11))); + assert_eq!(m.iter_mut().size_hint(), (0, Some(11))); + assert_eq!(m.iter_mut().rev().size_hint(), (0, Some(11))); +} + +#[test] +fn test_mut_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + for (k, v) in &mut m { + *v += k as isize; + } + + let mut it = m.iter(); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.next().unwrap(), (1, &3)); + assert_eq!(it.next().unwrap(), (3, &8)); + assert_eq!(it.next().unwrap(), (6, &16)); + assert_eq!(it.next().unwrap(), (10, &21)); + assert!(it.next().is_none()); +} + +#[test] +fn test_rev_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + let mut it = m.iter().rev(); + assert_eq!(it.next().unwrap(), (10, &11)); + assert_eq!(it.next().unwrap(), (6, &10)); + assert_eq!(it.next().unwrap(), (3, &5)); + assert_eq!(it.next().unwrap(), (1, &2)); + assert_eq!(it.next().unwrap(), (0, &1)); + assert!(it.next().is_none()); +} + +#[test] +fn test_mut_rev_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + for (k, v) in m.iter_mut().rev() { + *v += k as isize; + } + + let mut it = m.iter(); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.next().unwrap(), (1, &3)); + assert_eq!(it.next().unwrap(), (3, &8)); + assert_eq!(it.next().unwrap(), (6, &16)); + assert_eq!(it.next().unwrap(), (10, &21)); + assert!(it.next().is_none()); +} + +#[test] +fn test_move_iter() { + let mut m: VecMap> = VecMap::new(); + m.insert(1, box 2); + let mut called = false; + for (k, v) in m { + assert!(!called); + called = true; + assert_eq!(k, 1); + assert_eq!(v, box 2); + } + assert!(called); +} + +#[test] +fn test_drain_iterator() { + let mut map = VecMap::new(); + map.insert(1, "a"); + map.insert(3, "c"); + map.insert(2, "b"); + + let vec: Vec<_> = map.drain().collect(); + + assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); + assert_eq!(map.len(), 0); +} + +#[test] +fn test_append() { + let mut a = VecMap::new(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + + let mut b = VecMap::new(); + b.insert(3, "d"); // Overwrite element from a + b.insert(4, "e"); + b.insert(5, "f"); + + a.append(&mut b); + + assert_eq!(a.len(), 5); + assert_eq!(b.len(), 0); + // Capacity shouldn't change for possible reuse + assert!(b.capacity() >= 4); + + assert_eq!(a[1], "a"); + assert_eq!(a[2], "b"); + assert_eq!(a[3], "d"); + assert_eq!(a[4], "e"); + assert_eq!(a[5], "f"); +} + +#[test] +fn test_split_off() { + // Split within the key range + let mut a = VecMap::new(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + a.insert(4, "d"); + + let b = a.split_off(3); + + assert_eq!(a.len(), 2); + assert_eq!(b.len(), 2); + + assert_eq!(a[1], "a"); + assert_eq!(a[2], "b"); + + assert_eq!(b[3], "c"); + assert_eq!(b[4], "d"); + + // Split at 0 + a.clear(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + a.insert(4, "d"); + + let b = a.split_off(0); + + assert_eq!(a.len(), 0); + assert_eq!(b.len(), 4); + assert_eq!(b[1], "a"); + assert_eq!(b[2], "b"); + assert_eq!(b[3], "c"); + assert_eq!(b[4], "d"); + + // Split behind max_key + a.clear(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + a.insert(4, "d"); + + let b = a.split_off(5); + + assert_eq!(a.len(), 4); + assert_eq!(b.len(), 0); + assert_eq!(a[1], "a"); + assert_eq!(a[2], "b"); + assert_eq!(a[3], "c"); + assert_eq!(a[4], "d"); +} + +#[test] +fn test_show() { + let mut map = VecMap::new(); + let empty = VecMap::::new(); + + map.insert(1, 2); + map.insert(3, 4); + + let map_str = format!("{:?}", map); + assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); + assert_eq!(format!("{:?}", empty), "{}"); +} + +#[test] +fn test_clone() { + let mut a = VecMap::new(); + + a.insert(1, 'x'); + a.insert(4, 'y'); + a.insert(6, 'z'); + + assert!(a.clone() == a); +} + +#[test] +fn test_eq() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(a == b); + assert!(a.insert(0, 5).is_none()); + assert!(a != b); + assert!(b.insert(0, 4).is_none()); + assert!(a != b); + assert!(a.insert(5, 19).is_none()); + assert!(a != b); + assert!(!b.insert(0, 5).is_none()); + assert!(a != b); + assert!(b.insert(5, 19).is_none()); + assert!(a == b); + + a = VecMap::new(); + b = VecMap::with_capacity(1); + assert!(a == b); +} + +#[test] +fn test_lt() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(!(a < b) && !(b < a)); + assert!(b.insert(2, 5).is_none()); + assert!(a < b); + assert!(a.insert(2, 7).is_none()); + assert!(!(a < b) && b < a); + assert!(b.insert(1, 0).is_none()); + assert!(b < a); + assert!(a.insert(0, 6).is_none()); + assert!(a < b); + assert!(a.insert(6, 2).is_none()); + assert!(a < b && !(b < a)); +} + +#[test] +fn test_ord() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(a <= b && a >= b); + assert!(a.insert(1, 1).is_none()); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + assert!(b.insert(2, 2).is_none()); + assert!(b > a && b >= a); + assert!(a < b && a <= b); +} + +#[test] +fn test_hash() { + let mut x = VecMap::new(); + let mut y = VecMap::new(); + + assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); + x.insert(1, 'a'); + x.insert(2, 'b'); + x.insert(3, 'c'); + + y.insert(3, 'c'); + y.insert(2, 'b'); + y.insert(1, 'a'); + + assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); + + x.insert(1000, 'd'); + x.remove(&1000); + + assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); +} + +#[test] +fn test_from_iter() { + let xs = vec![(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]; + + let map: VecMap<_> = xs.iter().cloned().collect(); + + for &(k, v) in &xs { + assert_eq!(map.get(&k), Some(&v)); + } +} + +#[test] +fn test_index() { + let mut map = VecMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + assert_eq!(map[3], 4); +} + +#[test] +#[should_panic] +fn test_index_nonexistent() { + let mut map = VecMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + map[4]; +} + +#[test] +fn test_entry(){ + let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; + + let mut map: VecMap<_> = 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); +} + +mod bench { + use std::collections::VecMap; + + map_insert_rand_bench!{insert_rand_100, 100, VecMap} + map_insert_rand_bench!{insert_rand_10_000, 10_000, VecMap} + + map_insert_seq_bench!{insert_seq_100, 100, VecMap} + map_insert_seq_bench!{insert_seq_10_000, 10_000, VecMap} + + map_find_rand_bench!{find_rand_100, 100, VecMap} + map_find_rand_bench!{find_rand_10_000, 10_000, VecMap} + + map_find_seq_bench!{find_seq_100, 100, VecMap} + map_find_seq_bench!{find_seq_10_000, 10_000, VecMap} +} From a079d5e4d23dca9dfb68cb3a75a6d6a9babe2f84 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 11 Mar 2015 11:42:57 -0500 Subject: [PATCH 08/15] remove imports --- src/liballoc/heap.rs | 1 - src/libstd/old_io/mem.rs | 2 +- src/libstd/old_io/mod.rs | 2 +- src/libstd/old_io/process.rs | 2 +- src/libstd/old_path/posix.rs | 2 +- src/libstd/old_path/windows.rs | 2 +- src/libstd/process.rs | 2 +- src/test/compile-fail/method-suggestion-no-duplication.rs | 1 - 8 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index d1c8ab348d40a..25c6bda5f394d 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -388,7 +388,6 @@ mod imp { mod test { extern crate test; use self::test::Bencher; - use core::ptr::PtrExt; use boxed::Box; use heap; diff --git a/src/libstd/old_io/mem.rs b/src/libstd/old_io/mem.rs index a31b2e7627def..43182e4fcd6a8 100644 --- a/src/libstd/old_io/mem.rs +++ b/src/libstd/old_io/mem.rs @@ -398,7 +398,7 @@ impl<'a> Buffer for BufReader<'a> { mod test { extern crate "test" as test_crate; use old_io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek}; - use prelude::v1::{Ok, Err, range, Vec, Buffer, AsSlice, SliceExt}; + use prelude::v1::{Ok, Err, range, Vec, Buffer, AsSlice}; use prelude::v1::IteratorExt; use old_io; use iter::repeat; diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index 2c978177c5082..e1341e0e5cfc4 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -1853,7 +1853,7 @@ impl fmt::Display for FilePermission { mod tests { use self::BadReaderBehavior::*; use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput, Writer}; - use prelude::v1::{Ok, Vec, Buffer, SliceExt}; + use prelude::v1::{Ok, Vec, Buffer}; use usize; #[derive(Clone, PartialEq, Debug)] diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index 647ef7306178a..e5f2364337296 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -761,7 +761,7 @@ mod tests { use old_io::{Truncate, Write, TimedOut, timer, process, FileNotFound}; use prelude::v1::{Ok, Err, range, drop, Some, None, Vec}; use prelude::v1::{Path, String, Reader, Writer, Clone}; - use prelude::v1::{SliceExt, Str, AsSlice, ToString, GenericPath}; + use prelude::v1::{Str, AsSlice, ToString, GenericPath}; use old_io::fs::PathExtensions; use old_io::timer::*; use rt::running_on_valgrind; diff --git a/src/libstd/old_path/posix.rs b/src/libstd/old_path/posix.rs index 9ac7512c00b70..e35623d7b1a66 100644 --- a/src/libstd/old_path/posix.rs +++ b/src/libstd/old_path/posix.rs @@ -453,7 +453,7 @@ mod tests { use iter::IteratorExt; use option::Option::{self, Some, None}; use old_path::GenericPath; - use slice::{AsSlice, SliceExt}; + use slice::AsSlice; use str::{self, Str}; use string::ToString; use vec::Vec; diff --git a/src/libstd/old_path/windows.rs b/src/libstd/old_path/windows.rs index b74bee1242de7..ff4f083333b4e 100644 --- a/src/libstd/old_path/windows.rs +++ b/src/libstd/old_path/windows.rs @@ -1133,7 +1133,7 @@ mod tests { use iter::IteratorExt; use option::Option::{self, Some, None}; use old_path::GenericPath; - use slice::{AsSlice, SliceExt}; + use slice::AsSlice; use str::Str; use string::ToString; use vec::Vec; diff --git a/src/libstd/process.rs b/src/libstd/process.rs index db613db74cf4a..df8a5d27c7fa0 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -533,7 +533,7 @@ mod tests { use io::prelude::*; use prelude::v1::{Ok, Err, drop, Some, Vec}; use prelude::v1::{String, Clone}; - use prelude::v1::{SliceExt, Str, AsSlice, ToString, GenericPath}; + use prelude::v1::{Str, AsSlice, ToString, GenericPath}; use old_path; use old_io::fs::PathExtensions; use rt::running_on_valgrind; diff --git a/src/test/compile-fail/method-suggestion-no-duplication.rs b/src/test/compile-fail/method-suggestion-no-duplication.rs index d05e2ba0e1949..1d0c4254eda2e 100644 --- a/src/test/compile-fail/method-suggestion-no-duplication.rs +++ b/src/test/compile-fail/method-suggestion-no-duplication.rs @@ -19,5 +19,4 @@ fn main() { //~^ ERROR does not implement any method //~^^ HELP #1: `core::slice::SliceExt` //~^^^ HELP #2: `core::str::StrExt` - //~^^^^ HELP #3: `collections::slice::SliceExt` } From e09bf82a31fd5ae1df8cb2d775f372d41ecf5593 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 11 Mar 2015 19:28:58 -0500 Subject: [PATCH 09/15] enable enum_set tests --- src/libcollectionstest/enum_set.rs | 30 +++++++++++++++++------------- src/libcollectionstest/lib.rs | 3 +-- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/libcollectionstest/enum_set.rs b/src/libcollectionstest/enum_set.rs index a740c531c89d2..f04367147cb9d 100644 --- a/src/libcollectionstest/enum_set.rs +++ b/src/libcollectionstest/enum_set.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::EnumSet; +use std::mem; + +use collections::enum_set::{CLike, EnumSet}; + +use self::Foo::*; #[derive(Copy, PartialEq, Debug)] #[repr(usize)] @@ -144,23 +148,23 @@ fn test_contains() { fn test_iterator() { let mut e1: EnumSet = EnumSet::new(); - let elems: ::vec::Vec = e1.iter().collect(); + let elems: Vec = e1.iter().collect(); assert!(elems.is_empty()); e1.insert(A); - let elems: ::vec::Vec<_> = e1.iter().collect(); + let elems: Vec<_> = e1.iter().collect(); assert_eq!([A], elems); e1.insert(C); - let elems: ::vec::Vec<_> = e1.iter().collect(); + let elems: Vec<_> = e1.iter().collect(); assert_eq!([A,C], elems); e1.insert(C); - let elems: ::vec::Vec<_> = e1.iter().collect(); + let elems: Vec<_> = e1.iter().collect(); assert_eq!([A,C], elems); e1.insert(B); - let elems: ::vec::Vec<_> = e1.iter().collect(); + let elems: Vec<_> = e1.iter().collect(); assert_eq!([A,B,C], elems); } @@ -178,35 +182,35 @@ fn test_operators() { e2.insert(C); let e_union = e1 | e2; - let elems: ::vec::Vec<_> = e_union.iter().collect(); + let elems: Vec<_> = e_union.iter().collect(); assert_eq!([A,B,C], elems); let e_intersection = e1 & e2; - let elems: ::vec::Vec<_> = e_intersection.iter().collect(); + let elems: Vec<_> = e_intersection.iter().collect(); assert_eq!([C], elems); // Another way to express intersection let e_intersection = e1 - (e1 - e2); - let elems: ::vec::Vec<_> = e_intersection.iter().collect(); + let elems: Vec<_> = e_intersection.iter().collect(); assert_eq!([C], elems); let e_subtract = e1 - e2; - let elems: ::vec::Vec<_> = e_subtract.iter().collect(); + let elems: Vec<_> = e_subtract.iter().collect(); assert_eq!([A], elems); // Bitwise XOR of two sets, aka symmetric difference let e_symmetric_diff = e1 ^ e2; - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); + let elems: Vec<_> = e_symmetric_diff.iter().collect(); assert_eq!([A,B], elems); // Another way to express symmetric difference let e_symmetric_diff = (e1 - e2) | (e2 - e1); - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); + let elems: Vec<_> = e_symmetric_diff.iter().collect(); assert_eq!([A,B], elems); // Yet another way to express symmetric difference let e_symmetric_diff = (e1 | e2) - (e1 & e2); - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); + let elems: Vec<_> = e_symmetric_diff.iter().collect(); assert_eq!([A,B], elems); } diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 4cf1d01a4ee2a..7f029340d2594 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -32,8 +32,7 @@ extern crate unicode; mod binary_heap; mod bit; mod btree; -// FIXME(japaric) privacy -//mod enum_set; +mod enum_set; mod fmt; mod linked_list; mod slice; From cb5e4292911f3651aa3453ad1d81b2794f4b2583 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 11 Mar 2015 19:44:02 -0500 Subject: [PATCH 10/15] move some tests back to libcollections --- mk/tests.mk | 2 +- src/libcollections/lib.rs | 4 + src/libcollections/linked_list.rs | 191 +++++++++++++++++++ src/libcollections/macros.rs | 15 ++ src/libcollections/slice.rs | 93 +++++++++ src/libcollections/str.rs | 1 + src/libcollections/string.rs | 9 + src/libcollections/vec.rs | 6 + src/libcollections/vec_deque.rs | 245 ++++++++++++++++++++++++ src/libcollectionstest/linked_list.rs | 192 ------------------- src/libcollectionstest/slice.rs | 56 ------ src/libcollectionstest/vec_deque.rs | 262 -------------------------- 12 files changed, 565 insertions(+), 511 deletions(-) diff --git a/mk/tests.mk b/mk/tests.mk index 0851909a776e7..0d1067a87e006 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -22,7 +22,7 @@ $(eval $(call RUST_CRATE,coretest)) DEPS_collectionstest := $(eval $(call RUST_CRATE,collectionstest)) -TEST_TARGET_CRATES = $(filter-out collections core unicode,$(TARGET_CRATES)) \ +TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) \ collectionstest coretest TEST_DOC_CRATES = $(DOC_CRATES) TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans rustc_lint,\ diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 0d53215a59659..b75f346c188fb 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -47,6 +47,9 @@ extern crate core; extern crate unicode; extern crate alloc; +#[cfg(test)] #[macro_use] extern crate std; +#[cfg(test)] extern crate test; + pub use binary_heap::BinaryHeap; pub use bit_vec::BitVec; pub use bit_set::BitSet; @@ -131,6 +134,7 @@ pub mod btree_set { #[doc(hidden)] pub fn fixme_14344_be_sure_to_link_to_collections() {} +#[cfg(not(test))] mod std { pub use core::ops; // RangeFull } diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 0799e14e6574d..9e0a6d0438100 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -938,3 +938,194 @@ impl Hash for LinkedList { } } } + +#[cfg(test)] +mod test { + use std::clone::Clone; + use std::iter::{Iterator, IteratorExt}; + use std::option::Option::{Some, None, self}; + use std::rand; + use std::thread; + use std::vec::Vec; + + use super::{LinkedList, Node}; + + #[cfg(test)] + fn list_from(v: &[T]) -> LinkedList { + v.iter().cloned().collect() + } + + pub fn check_links(list: &LinkedList) { + let mut len = 0; + let mut last_ptr: Option<&Node> = None; + let mut node_ptr: &Node; + match list.list_head { + None => { assert_eq!(0, list.length); return } + Some(ref node) => node_ptr = &**node, + } + loop { + match (last_ptr, node_ptr.prev.resolve_immut()) { + (None , None ) => {} + (None , _ ) => panic!("prev link for list_head"), + (Some(p), Some(pptr)) => { + assert_eq!(p as *const Node, pptr as *const Node); + } + _ => panic!("prev link is none, not good"), + } + match node_ptr.next { + Some(ref next) => { + last_ptr = Some(node_ptr); + node_ptr = &**next; + len += 1; + } + None => { + len += 1; + break; + } + } + } + assert_eq!(len, list.length); + } + + #[test] + fn test_append() { + // Empty to empty + { + let mut m = LinkedList::::new(); + let mut n = LinkedList::new(); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 0); + assert_eq!(n.len(), 0); + } + // Non-empty to empty + { + let mut m = LinkedList::new(); + let mut n = LinkedList::new(); + n.push_back(2); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + assert_eq!(n.len(), 0); + check_links(&m); + } + // Empty to non-empty + { + let mut m = LinkedList::new(); + let mut n = LinkedList::new(); + m.push_back(2); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + check_links(&m); + } + + // Non-empty to non-empty + let v = vec![1,2,3,4,5]; + let u = vec![9,8,1,2,3,4,5]; + let mut m = list_from(&v); + let mut n = list_from(&u); + m.append(&mut n); + check_links(&m); + let mut sum = v; + sum.push_all(&u); + assert_eq!(sum.len(), m.len()); + for elt in sum { + assert_eq!(m.pop_front(), Some(elt)) + } + assert_eq!(n.len(), 0); + // let's make sure it's working properly, since we + // did some direct changes to private members + n.push_back(3); + assert_eq!(n.len(), 1); + assert_eq!(n.pop_front(), Some(3)); + check_links(&n); + } + + #[test] + fn test_insert_prev() { + let mut m = list_from(&[0,2,4,6,8]); + let len = m.len(); + { + let mut it = m.iter_mut(); + it.insert_next(-2); + loop { + match it.next() { + None => break, + Some(elt) => { + it.insert_next(*elt + 1); + match it.peek_next() { + Some(x) => assert_eq!(*x, *elt + 2), + None => assert_eq!(8, *elt), + } + } + } + } + it.insert_next(0); + it.insert_next(1); + } + check_links(&m); + assert_eq!(m.len(), 3 + len * 2); + assert_eq!(m.into_iter().collect::>(), [-2,0,1,2,3,4,5,6,7,8,9,0,1]); + } + + #[test] + fn test_send() { + let n = list_from(&[1,2,3]); + thread::spawn(move || { + check_links(&n); + let a: &[_] = &[&1,&2,&3]; + assert_eq!(a, n.iter().collect::>()); + }).join().ok().unwrap(); + } + + #[test] + fn test_fuzz() { + for _ in 0..25 { + fuzz_test(3); + fuzz_test(16); + fuzz_test(189); + } + } + + #[cfg(test)] + fn fuzz_test(sz: i32) { + let mut m: LinkedList<_> = LinkedList::new(); + let mut v = vec![]; + for i in 0..sz { + check_links(&m); + let r: u8 = rand::random(); + match r % 6 { + 0 => { + m.pop_back(); + v.pop(); + } + 1 => { + if !v.is_empty() { + m.pop_front(); + v.remove(0); + } + } + 2 | 4 => { + m.push_front(-i); + v.insert(0, -i); + } + 3 | 5 | _ => { + m.push_back(i); + v.push(i); + } + } + } + + check_links(&m); + + let mut i = 0; + for (a, &b) in m.into_iter().zip(v.iter()) { + i += 1; + assert_eq!(a, b); + } + assert_eq!(i, v.len()); + } +} diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index cb84e01e4f79a..be3d8f8dbb63d 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -71,6 +71,7 @@ macro_rules! vec { /// Note that unlike array expressions this syntax supports all elements /// which implement `Clone` and the number of elements doesn't have to be /// a constant. +#[cfg(not(test))] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! vec { @@ -83,6 +84,20 @@ macro_rules! vec { ($($x:expr,)*) => (vec![$($x),*]) } +// HACK: `impl [T]` is not available in cfg(test), use `::slice::into_vec`, instead of +// `<[T]>::to_vec` +#[cfg(not(stage0))] +#[cfg(test)] +macro_rules! vec { + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),*) => ( + $crate::slice::into_vec($crate::boxed::Box::new([$($x),*])) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + /// Use the syntax described in `std::fmt` to create a value of type `String`. /// See `std::fmt` for more information. /// diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 15b67376887c2..dafe0edbf32c7 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1083,9 +1083,36 @@ impl SliceExt for [T] { } } +// HACK: With cfg(test) `impl [T]` is not available, these three functions are actually methods +// that are in `impl [T]` but not in `core::slice::SliceExt` - this is only need for testing +#[cfg(test)] +pub fn into_vec(mut b: Box<[T]>) -> Vec { + unsafe { + let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len()); + mem::forget(b); + xs + } +} + +#[cfg(test)] +pub fn permutations(s: &[T]) -> Permutations where T: Clone { + Permutations{ + swaps: ElementSwaps::new(s.len()), + v: ::slice::to_vec(s), + } +} + +#[cfg(test)] +pub fn to_vec(s: &[T]) -> Vec where T: Clone { + let mut vector = Vec::with_capacity(s.len()); + vector.push_all(s); + vector +} + #[cfg(not(stage0))] /// Allocating extension methods for slices. #[lang = "slice"] +#[cfg(not(test))] #[stable(feature = "rust1", since = "1.0.0")] impl [T] { /// Sorts the slice, in place, using `compare` to compare @@ -2022,7 +2049,13 @@ impl BorrowMut<[T]> for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for [T] { type Owned = Vec; + #[cfg(not(test))] fn to_owned(&self) -> Vec { self.to_vec() } + + // HACK: `impl [T]` is not available in cfg(test), use `::slice::to_vec` instead of + // `<[T]>::to_vec` + #[cfg(test)] + fn to_owned(&self) -> Vec { ::slice::to_vec(self) } } //////////////////////////////////////////////////////////////////////////////// @@ -2339,3 +2372,63 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order old } } + +#[cfg(test)] +mod test { + use core::iter::{Iterator, IteratorExt}; + use core::option::Option::{None, Some}; + use string::ToString; + + #[test] + fn test_permutations() { + { + let v: [i32; 0] = []; + let mut it = ::slice::permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 1); + assert_eq!(max_opt.unwrap(), 1); + assert_eq!(it.next(), Some(::slice::to_vec(&v))); + assert_eq!(it.next(), None); + } + { + let v = ["Hello".to_string()]; + let mut it = ::slice::permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 1); + assert_eq!(max_opt.unwrap(), 1); + assert_eq!(it.next(), Some(::slice::to_vec(&v))); + assert_eq!(it.next(), None); + } + { + let v = [1, 2, 3]; + let mut it = ::slice::permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 3*2); + assert_eq!(max_opt.unwrap(), 3*2); + assert_eq!(it.next().unwrap(), [1,2,3]); + assert_eq!(it.next().unwrap(), [1,3,2]); + assert_eq!(it.next().unwrap(), [3,1,2]); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 3); + assert_eq!(max_opt.unwrap(), 3); + assert_eq!(it.next().unwrap(), [3,2,1]); + assert_eq!(it.next().unwrap(), [2,3,1]); + assert_eq!(it.next().unwrap(), [2,1,3]); + assert_eq!(it.next(), None); + } + { + // check that we have N! permutations + let v = ['A', 'B', 'C', 'D', 'E', 'F']; + let mut amt = 0; + let mut it = ::slice::permutations(&v); + let (min_size, max_opt) = it.size_hint(); + for _perm in it.by_ref() { + amt += 1; + } + assert_eq!(amt, it.swaps.swaps_made); + assert_eq!(amt, min_size); + assert_eq!(amt, 2 * 3 * 4 * 5 * 6); + assert_eq!(amt, max_opt.unwrap()); + } + } +} diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index fc93b0b75a7ab..a99372f178b2c 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1562,6 +1562,7 @@ impl StrExt for str { #[cfg(not(stage0))] /// Any string that can be represented as a slice. #[lang = "str"] +#[cfg(not(test))] #[stable(feature = "rust1", since = "1.0.0")] impl str { /// Escapes each char in `s` with `char::escape_default`. diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 6d1b929cf601c..fdc7cf993b118 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -113,10 +113,19 @@ impl String { #[inline] #[unstable(feature = "collections", reason = "needs investigation to see if to_string() can match perf")] + #[cfg(not(test))] pub fn from_str(string: &str) -> String { String { vec: <[_]>::to_vec(string.as_bytes()) } } + // HACK: `impl [T]` is not available in cfg(test), use `::slice::to_vec` instead of + // `<[T]>::to_vec` + #[inline] + #[cfg(test)] + pub fn from_str(string: &str) -> String { + String { vec: ::slice::to_vec(string.as_bytes()) } + } + /// Returns the vector as a string buffer, if possible, taking care not to /// copy it. /// diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 22da0a191ca24..6aaebe08f5c26 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1287,8 +1287,14 @@ impl Clone for Vec { fn clone(&self) -> Vec { ::slice::SliceExt::to_vec(&**self) } #[cfg(not(stage0))] + #[cfg(not(test))] fn clone(&self) -> Vec { <[T]>::to_vec(&**self) } + // HACK: `impl [T]` not available in cfg(test), use `::slice::to_vec` instead of `<[T]>::to_vec` + #[cfg(not(stage0))] + #[cfg(test)] + fn clone(&self) -> Vec { ::slice::to_vec(&**self) } + fn clone_from(&mut self, other: &Vec) { // drop anything in self that will not be overwritten if self.len() > other.len() { diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 700ee059a7fa5..95d43fa8fc0d5 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -1768,3 +1768,248 @@ impl fmt::Debug for VecDeque { write!(f, "]") } } + +#[cfg(test)] +mod test { + use core::iter::{IteratorExt, self}; + use core::option::Option::Some; + + use test; + + use super::VecDeque; + + #[bench] + fn bench_push_back_100(b: &mut test::Bencher) { + let mut deq = VecDeque::with_capacity(101); + b.iter(|| { + for i in 0..100 { + deq.push_back(i); + } + deq.head = 0; + deq.tail = 0; + }) + } + + #[bench] + fn bench_push_front_100(b: &mut test::Bencher) { + let mut deq = VecDeque::with_capacity(101); + b.iter(|| { + for i in 0..100 { + deq.push_front(i); + } + deq.head = 0; + deq.tail = 0; + }) + } + + #[bench] + fn bench_pop_back_100(b: &mut test::Bencher) { + let mut deq= VecDeque::::with_capacity(101); + + b.iter(|| { + deq.head = 100; + deq.tail = 0; + while !deq.is_empty() { + test::black_box(deq.pop_back()); + } + }) + } + + #[bench] + fn bench_pop_front_100(b: &mut test::Bencher) { + let mut deq = VecDeque::::with_capacity(101); + + b.iter(|| { + deq.head = 100; + deq.tail = 0; + while !deq.is_empty() { + test::black_box(deq.pop_front()); + } + }) + } + + #[test] + fn test_swap_front_back_remove() { + fn test(back: bool) { + // This test checks that every single combination of tail position and length is tested. + // Capacity 15 should be large enough to cover every case. + let mut tester = VecDeque::with_capacity(15); + let usable_cap = tester.capacity(); + let final_len = usable_cap / 2; + + for len in 0..final_len { + let expected = if back { + (0..len).collect() + } else { + (0..len).rev().collect() + }; + for tail_pos in 0..usable_cap { + tester.tail = tail_pos; + tester.head = tail_pos; + if back { + for i in 0..len * 2 { + tester.push_front(i); + } + for i in 0..len { + assert_eq!(tester.swap_back_remove(i), Some(len * 2 - 1 - i)); + } + } else { + for i in 0..len * 2 { + tester.push_back(i); + } + for i in 0..len { + let idx = tester.len() - 1 - i; + assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i)); + } + } + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert_eq!(tester, expected); + } + } + } + test(true); + test(false); + } + + #[test] + fn test_insert() { + // This test checks that every single combination of tail position, length, and + // insertion position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + + // len is the length *after* insertion + for len in 1..cap { + // 0, 1, 2, .., len - 1 + let expected = iter::count(0, 1).take(len).collect(); + for tail_pos in 0..cap { + for to_insert in 0..len { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + if i != to_insert { + tester.push_back(i); + } + } + tester.insert(to_insert, to_insert); + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert_eq!(tester, expected); + } + } + } + } + + #[test] + fn test_remove() { + // This test checks that every single combination of tail position, length, and + // removal position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *after* removal + for len in 0..cap - 1 { + // 0, 1, 2, .., len - 1 + let expected = iter::count(0, 1).take(len).collect(); + for tail_pos in 0..cap { + for to_remove in 0..len + 1 { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + if i == to_remove { + tester.push_back(1234); + } + tester.push_back(i); + } + if to_remove == len { + tester.push_back(1234); + } + tester.remove(to_remove); + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert_eq!(tester, expected); + } + } + } + } + + #[test] + fn test_shrink_to_fit() { + // This test checks that every single combination of head and tail position, + // is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + tester.reserve(63); + let max_cap = tester.capacity(); + + for len in 0..cap + 1 { + // 0, 1, 2, .., len - 1 + let expected = iter::count(0, 1).take(len).collect(); + for tail_pos in 0..max_cap + 1 { + tester.tail = tail_pos; + tester.head = tail_pos; + tester.reserve(63); + for i in 0..len { + tester.push_back(i); + } + tester.shrink_to_fit(); + assert!(tester.capacity() <= cap); + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert_eq!(tester, expected); + } + } + } + + #[test] + fn test_split_off() { + // This test checks that every single combination of tail position, length, and + // split position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *before* splitting + for len in 0..cap { + // index to split at + for at in 0..len + 1 { + // 0, 1, 2, .., at - 1 (may be empty) + let expected_self = iter::count(0, 1).take(at).collect(); + // at, at + 1, .., len - 1 (may be empty) + let expected_other = iter::count(at, 1).take(len - at).collect(); + + for tail_pos in 0..cap { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + tester.push_back(i); + } + let result = tester.split_off(at); + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert!(result.tail < result.cap); + assert!(result.head < result.cap); + assert_eq!(tester, expected_self); + assert_eq!(result, expected_other); + } + } + } + } +} diff --git a/src/libcollectionstest/linked_list.rs b/src/libcollectionstest/linked_list.rs index 95d49885b3b2d..fd73938095f09 100644 --- a/src/libcollectionstest/linked_list.rs +++ b/src/libcollectionstest/linked_list.rs @@ -13,41 +13,6 @@ use std::hash::{SipHasher, self}; use test; -// FIXME(japaric) privacy -/* -pub fn check_links(list: &LinkedList) { - let mut len = 0; - let mut last_ptr: Option<&Node> = None; - let mut node_ptr: &Node; - match list.list_head { - None => { assert_eq!(0, list.length); return } - Some(ref node) => node_ptr = &**node, - } - loop { - match (last_ptr, node_ptr.prev.resolve_immut()) { - (None , None ) => {} - (None , _ ) => panic!("prev link for list_head"), - (Some(p), Some(pptr)) => { - assert_eq!(p as *const Node, pptr as *const Node); - } - _ => panic!("prev link is none, not good"), - } - match node_ptr.next { - Some(ref next) => { - last_ptr = Some(node_ptr); - node_ptr = &**next; - len += 1; - } - None => { - len += 1; - break; - } - } - } - assert_eq!(len, list.length); -} -*/ - #[test] fn test_basic() { let mut m = LinkedList::>::new(); @@ -98,66 +63,6 @@ fn list_from(v: &[T]) -> LinkedList { v.iter().cloned().collect() } -// FIXME(japaric) privacy -/* -#[test] -fn test_append() { - // Empty to empty - { - let mut m = LinkedList::::new(); - let mut n = LinkedList::new(); - m.append(&mut n); - check_links(&m); - assert_eq!(m.len(), 0); - assert_eq!(n.len(), 0); - } - // Non-empty to empty - { - let mut m = LinkedList::new(); - let mut n = LinkedList::new(); - n.push_back(2); - m.append(&mut n); - check_links(&m); - assert_eq!(m.len(), 1); - assert_eq!(m.pop_back(), Some(2)); - assert_eq!(n.len(), 0); - check_links(&m); - } - // Empty to non-empty - { - let mut m = LinkedList::new(); - let mut n = LinkedList::new(); - m.push_back(2); - m.append(&mut n); - check_links(&m); - assert_eq!(m.len(), 1); - assert_eq!(m.pop_back(), Some(2)); - check_links(&m); - } - - // Non-empty to non-empty - let v = vec![1,2,3,4,5]; - let u = vec![9,8,1,2,3,4,5]; - let mut m = list_from(&v); - let mut n = list_from(&u); - m.append(&mut n); - check_links(&m); - let mut sum = v; - sum.push_all(&u); - assert_eq!(sum.len(), m.len()); - for elt in sum { - assert_eq!(m.pop_front(), Some(elt)) - } - assert_eq!(n.len(), 0); - // let's make sure it's working properly, since we - // did some direct changes to private members - n.push_back(3); - assert_eq!(n.len(), 1); - assert_eq!(n.pop_front(), Some(3)); - check_links(&n); -} -*/ - #[test] fn test_split_off() { // singleton @@ -318,36 +223,6 @@ fn test_iterator_mut_double_end() { assert!(it.next().is_none()); } -// FIXME(japaric) privacy -/* -#[test] -fn test_insert_prev() { - let mut m = list_from(&[0,2,4,6,8]); - let len = m.len(); - { - let mut it = m.iter_mut(); - it.insert_next(-2); - loop { - match it.next() { - None => break, - Some(elt) => { - it.insert_next(*elt + 1); - match it.peek_next() { - Some(x) => assert_eq!(*x, *elt + 2), - None => assert_eq!(8, *elt), - } - } - } - } - it.insert_next(0); - it.insert_next(1); - } - check_links(&m); - assert_eq!(m.len(), 3 + len * 2); - assert_eq!(m.into_iter().collect::>(), [-2,0,1,2,3,4,5,6,7,8,9,0,1]); -} -*/ - #[test] fn test_mut_rev_iter() { let mut m = generate_test(); @@ -362,19 +237,6 @@ fn test_mut_rev_iter() { assert!(it.next().is_none()); } -// FIXME(japaric) privacy -/* -#[test] -fn test_send() { - let n = list_from(&[1,2,3]); - thread::spawn(move || { - check_links(&n); - let a: &[_] = &[&1,&2,&3]; - assert_eq!(a, n.iter().collect::>()); - }).join().ok().unwrap(); -} -*/ - #[test] fn test_eq() { let mut n = list_from(&[]); @@ -450,18 +312,6 @@ fn test_ord_nan() { assert!(s >= one); } -// FIXME(japaric) privacy -/* -#[test] -fn test_fuzz() { - for _ in 0..25 { - fuzz_test(3); - fuzz_test(16); - fuzz_test(189); - } -} -*/ - #[test] fn test_show() { let list: LinkedList<_> = (0..10).collect(); @@ -471,48 +321,6 @@ fn test_show() { assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]"); } -// FIXME(japaric) privacy -/* -#[cfg(test)] -fn fuzz_test(sz: i32) { - let mut m: LinkedList<_> = LinkedList::new(); - let mut v = vec![]; - for i in 0..sz { - check_links(&m); - let r: u8 = rand::random(); - match r % 6 { - 0 => { - m.pop_back(); - v.pop(); - } - 1 => { - if !v.is_empty() { - m.pop_front(); - v.remove(0); - } - } - 2 | 4 => { - m.push_front(-i); - v.insert(0, -i); - } - 3 | 5 | _ => { - m.push_back(i); - v.push(i); - } - } - } - - check_links(&m); - - let mut i = 0; - for (a, &b) in m.into_iter().zip(v.iter()) { - i += 1; - assert_eq!(a, b); - } - assert_eq!(i, v.len()); -} -*/ - #[bench] fn bench_collect_into(b: &mut test::Bencher) { let v = &[0; 64]; diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index 7d50a1a13f2ab..0c3c82eea780f 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -406,62 +406,6 @@ fn test_element_swaps() { } } -// FIXME(japaric) privacy -/* -#[test] -fn test_permutations() { - { - let v: [i32; 0] = []; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 1); - assert_eq!(max_opt.unwrap(), 1); - assert_eq!(it.next(), Some(v.to_vec())); - assert_eq!(it.next(), None); - } - { - let v = ["Hello".to_string()]; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 1); - assert_eq!(max_opt.unwrap(), 1); - assert_eq!(it.next(), Some(v.to_vec())); - assert_eq!(it.next(), None); - } - { - let v = [1, 2, 3]; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 3*2); - assert_eq!(max_opt.unwrap(), 3*2); - assert_eq!(it.next(), Some(vec![1,2,3])); - assert_eq!(it.next(), Some(vec![1,3,2])); - assert_eq!(it.next(), Some(vec![3,1,2])); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 3); - assert_eq!(max_opt.unwrap(), 3); - assert_eq!(it.next(), Some(vec![3,2,1])); - assert_eq!(it.next(), Some(vec![2,3,1])); - assert_eq!(it.next(), Some(vec![2,1,3])); - assert_eq!(it.next(), None); - } - { - // check that we have N! permutations - let v = ['A', 'B', 'C', 'D', 'E', 'F']; - let mut amt = 0; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - for _perm in it.by_ref() { - amt += 1; - } - assert_eq!(amt, it.swaps.swaps_made); - assert_eq!(amt, min_size); - assert_eq!(amt, 2 * 3 * 4 * 5 * 6); - assert_eq!(amt, max_opt.unwrap()); - } -} -*/ - #[test] fn test_lexicographic_permutations() { let v : &mut[_] = &mut[1, 2, 3, 4, 5]; diff --git a/src/libcollectionstest/vec_deque.rs b/src/libcollectionstest/vec_deque.rs index ba2ed36de2110..38f358c150531 100644 --- a/src/libcollectionstest/vec_deque.rs +++ b/src/libcollectionstest/vec_deque.rs @@ -137,68 +137,6 @@ fn bench_new(b: &mut test::Bencher) { }) } -// FIXME(japaric) privacy -/* -#[bench] -fn bench_push_back_100(b: &mut test::Bencher) { - let mut deq = VecDeque::with_capacity(101); - b.iter(|| { - for i in 0..100 { - deq.push_back(i); - } - deq.head = 0; - deq.tail = 0; - }) -} -*/ - -// FIXME(japaric) privacy -/* -#[bench] -fn bench_push_front_100(b: &mut test::Bencher) { - let mut deq = VecDeque::with_capacity(101); - b.iter(|| { - for i in 0..100 { - deq.push_front(i); - } - deq.head = 0; - deq.tail = 0; - }) -} -*/ - -// FIXME(japaric) privacy -/* -#[bench] -fn bench_pop_back_100(b: &mut test::Bencher) { - let mut deq= VecDeque::::with_capacity(101); - - b.iter(|| { - deq.head = 100; - deq.tail = 0; - while !deq.is_empty() { - test::black_box(deq.pop_back()); - } - }) -} -*/ - -// FIXME(japaric) privacy -/* -#[bench] -fn bench_pop_front_100(b: &mut test::Bencher) { - let mut deq = VecDeque::::with_capacity(101); - - b.iter(|| { - deq.head = 100; - deq.tail = 0; - while !deq.is_empty() { - test::black_box(deq.pop_front()); - } - }) -} -*/ - #[bench] fn bench_grow_1025(b: &mut test::Bencher) { b.iter(|| { @@ -860,165 +798,6 @@ fn test_get_mut() { assert_eq!(ring.get_mut(2), None); } -// FIXME(japaric) privacy -/* -#[test] -fn test_swap_front_back_remove() { - fn test(back: bool) { - // This test checks that every single combination of tail position and length is tested. - // Capacity 15 should be large enough to cover every case. - let mut tester = VecDeque::with_capacity(15); - let usable_cap = tester.capacity(); - let final_len = usable_cap / 2; - - for len in 0..final_len { - let expected = if back { - (0..len).collect() - } else { - (0..len).rev().collect() - }; - for tail_pos in 0..usable_cap { - tester.tail = tail_pos; - tester.head = tail_pos; - if back { - for i in 0..len * 2 { - tester.push_front(i); - } - for i in 0..len { - assert_eq!(tester.swap_back_remove(i), Some(len * 2 - 1 - i)); - } - } else { - for i in 0..len * 2 { - tester.push_back(i); - } - for i in 0..len { - let idx = tester.len() - 1 - i; - assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i)); - } - } - assert!(tester.tail < tester.cap); - assert!(tester.head < tester.cap); - assert_eq!(tester, expected); - } - } - } - test(true); - test(false); -} -*/ - -// FIXME(japaric) privacy -/* -#[test] -fn test_insert() { - // This test checks that every single combination of tail position, length, and - // insertion position is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - - - // len is the length *after* insertion - for len in 1..cap { - // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); - for tail_pos in 0..cap { - for to_insert in 0..len { - tester.tail = tail_pos; - tester.head = tail_pos; - for i in 0..len { - if i != to_insert { - tester.push_back(i); - } - } - tester.insert(to_insert, to_insert); - assert!(tester.tail < tester.cap); - assert!(tester.head < tester.cap); - assert_eq!(tester, expected); - } - } - } -} -*/ - -// FIXME(japaric) privacy -/* -#[test] -fn test_remove() { - // This test checks that every single combination of tail position, length, and - // removal position is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - - // len is the length *after* removal - for len in 0..cap - 1 { - // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); - for tail_pos in 0..cap { - for to_remove in 0..len + 1 { - tester.tail = tail_pos; - tester.head = tail_pos; - for i in 0..len { - if i == to_remove { - tester.push_back(1234); - } - tester.push_back(i); - } - if to_remove == len { - tester.push_back(1234); - } - tester.remove(to_remove); - assert!(tester.tail < tester.cap); - assert!(tester.head < tester.cap); - assert_eq!(tester, expected); - } - } - } -} -*/ - -// FIXME(japaric) privacy -/* -#[test] -fn test_shrink_to_fit() { - // This test checks that every single combination of head and tail position, - // is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - tester.reserve(63); - let max_cap = tester.capacity(); - - for len in 0..cap + 1 { - // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); - for tail_pos in 0..max_cap + 1 { - tester.tail = tail_pos; - tester.head = tail_pos; - tester.reserve(63); - for i in 0..len { - tester.push_back(i); - } - tester.shrink_to_fit(); - assert!(tester.capacity() <= cap); - assert!(tester.tail < tester.cap); - assert!(tester.head < tester.cap); - assert_eq!(tester, expected); - } - } -} -*/ - #[test] fn test_front() { let mut ring = VecDeque::new(); @@ -1087,47 +866,6 @@ fn test_as_mut_slices() { assert_eq!(ring.capacity() as i32, cap); } -// FIXME(japaric) privacy -/* -#[test] -fn test_split_off() { - // This test checks that every single combination of tail position, length, and - // split position is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - - // len is the length *before* splitting - for len in 0..cap { - // index to split at - for at in 0..len + 1 { - // 0, 1, 2, .., at - 1 (may be empty) - let expected_self = iter::count(0, 1).take(at).collect(); - // at, at + 1, .., len - 1 (may be empty) - let expected_other = iter::count(at, 1).take(len - at).collect(); - - for tail_pos in 0..cap { - tester.tail = tail_pos; - tester.head = tail_pos; - for i in 0..len { - tester.push_back(i); - } - let result = tester.split_off(at); - assert!(tester.tail < tester.cap); - assert!(tester.head < tester.cap); - assert!(result.tail < result.cap); - assert!(result.head < result.cap); - assert_eq!(tester, expected_self); - assert_eq!(result, expected_other); - } - } - } -} -*/ - #[test] fn test_append() { let mut a: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); From 6d49476e7bda8bff039ae1bff95aaf3ac22ebbc8 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 12 Mar 2015 00:25:33 -0500 Subject: [PATCH 11/15] preemptively fix windows compilation errors --- src/libstd/dynamic_lib.rs | 2 ++ src/libstd/sys/windows/process2.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index 90373441edcad..d06b027adf65c 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -272,7 +272,9 @@ mod dl { use ptr; use result::Result; use result::Result::{Ok, Err}; + #[cfg(stage0)] use slice::SliceExt; + #[cfg(stage0)] use str::StrExt; use str; use string::String; diff --git a/src/libstd/sys/windows/process2.rs b/src/libstd/sys/windows/process2.rs index 4fbaabc9ecc2b..e3cf5da59f0ee 100644 --- a/src/libstd/sys/windows/process2.rs +++ b/src/libstd/sys/windows/process2.rs @@ -128,6 +128,7 @@ impl Process { use env::split_paths; use mem; use iter::IteratorExt; + #[cfg(stage0)] use str::StrExt; // To have the spawning semantics of unix/windows stay the same, we need to From 59749087f8c42d767e0bf89e867664f4aea3a357 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 12 Mar 2015 00:41:10 -0500 Subject: [PATCH 12/15] fix after rebase --- src/libcollections/str.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index a99372f178b2c..e92e340b86cdd 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -67,6 +67,7 @@ use core::option::Option::{self, Some, None}; use core::result::Result; use core::slice::AsSlice; use core::str as core_str; +#[cfg(stage0)] use unicode::char::CharExt; use unicode::str::{UnicodeStr, Utf16Encoder}; From 3ab26f84698bf30572f3bc9336570c422f59aa2a Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 13 Mar 2015 18:32:42 -0500 Subject: [PATCH 13/15] join lines in makefile --- mk/tests.mk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mk/tests.mk b/mk/tests.mk index 0d1067a87e006..2fb33eb7db898 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -22,8 +22,7 @@ $(eval $(call RUST_CRATE,coretest)) DEPS_collectionstest := $(eval $(call RUST_CRATE,collectionstest)) -TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) \ - collectionstest coretest +TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) collectionstest coretest TEST_DOC_CRATES = $(DOC_CRATES) TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans rustc_lint,\ $(HOST_CRATES)) From 8256241d3af28bd835b267e27b6e24aeb5e799bd Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 13 Mar 2015 19:13:35 -0500 Subject: [PATCH 14/15] impl f{32,64} --- src/librustc/middle/check_match.rs | 1 + src/libserialize/json.rs | 2 +- src/libstd/num/f32.rs | 1230 ++++++++++++++++++++++++++++ src/libstd/num/f64.rs | 1229 +++++++++++++++++++++++++++ src/libstd/num/float_macros.rs | 10 + src/libsyntax/parse/parser.rs | 1 + 6 files changed, 2472 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 6c140d73be0c8..313f034021f2f 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -27,6 +27,7 @@ use middle::ty; use std::cmp::Ordering; use std::fmt; use std::iter::{range_inclusive, AdditiveIterator, FromIterator, IntoIterator, repeat}; +#[cfg(stage0)] use std::num::Float; use std::slice; use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat}; diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index d0ef89e811bd4..366b90cfbfd32 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -204,6 +204,7 @@ use std::io::prelude::*; use std::io; use std::mem::{swap}; use std::num::FpCategory as Fp; +#[cfg(stage0)] use std::num::{Float, Int}; use std::ops::Index; use std::str::FromStr; @@ -2622,7 +2623,6 @@ mod tests { StackElement, Stack, Decoder, Encoder, EncoderError}; use std::{i64, u64, f32, f64}; use std::collections::BTreeMap; - use std::num::Float; use std::string; #[derive(RustcDecodable, Eq, PartialEq, Debug)] diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 969dd35ba2288..a7825c4f93aa8 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -357,6 +357,1236 @@ impl Float for f32 { } } +#[cfg(not(stage0))] +#[cfg(not(test))] +#[lang = "f32"] +#[stable(feature = "rust1", since = "1.0.0")] +impl f32 { + // inlined methods from `num::Float` + /// Returns the `NaN` value. + /// + /// ``` + /// use std::num::Float; + /// + /// let nan: f32 = Float::nan(); + /// + /// assert!(nan.is_nan()); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn nan() -> f32 { num::Float::nan() } + + /// Returns the infinite value. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let infinity: f32 = Float::infinity(); + /// + /// assert!(infinity.is_infinite()); + /// assert!(!infinity.is_finite()); + /// assert!(infinity > f32::MAX); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn infinity() -> f32 { num::Float::infinity() } + + /// Returns the negative infinite value. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let neg_infinity: f32 = Float::neg_infinity(); + /// + /// assert!(neg_infinity.is_infinite()); + /// assert!(!neg_infinity.is_finite()); + /// assert!(neg_infinity < f32::MIN); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn neg_infinity() -> f32 { num::Float::neg_infinity() } + + /// Returns `0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let inf: f32 = Float::infinity(); + /// let zero: f32 = Float::zero(); + /// let neg_zero: f32 = Float::neg_zero(); + /// + /// assert_eq!(zero, neg_zero); + /// assert_eq!(7.0f32/inf, zero); + /// assert_eq!(zero * 10.0, zero); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn zero() -> f32 { num::Float::zero() } + + /// Returns `-0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let inf: f32 = Float::infinity(); + /// let zero: f32 = Float::zero(); + /// let neg_zero: f32 = Float::neg_zero(); + /// + /// assert_eq!(zero, neg_zero); + /// assert_eq!(7.0f32/inf, zero); + /// assert_eq!(zero * 10.0, zero); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn neg_zero() -> f32 { num::Float::neg_zero() } + + /// Returns `1.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let one: f32 = Float::one(); + /// + /// assert_eq!(one, 1.0f32); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn one() -> f32 { num::Float::one() } + + // FIXME (#5527): These should be associated constants + + /// Deprecated: use `std::f32::MANTISSA_DIGITS` or `std::f64::MANTISSA_DIGITS` + /// instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MANTISSA_DIGITS` or \ + `std::f64::MANTISSA_DIGITS` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn mantissa_digits(unused_self: Option) -> uint { + num::Float::mantissa_digits(unused_self) + } + + /// Deprecated: use `std::f32::DIGITS` or `std::f64::DIGITS` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn digits(unused_self: Option) -> uint { num::Float::digits(unused_self) } + + /// Deprecated: use `std::f32::EPSILON` or `std::f64::EPSILON` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn epsilon() -> f32 { num::Float::epsilon() } + + /// Deprecated: use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn min_exp(unused_self: Option) -> int { num::Float::min_exp(unused_self) } + + /// Deprecated: use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn max_exp(unused_self: Option) -> int { num::Float::max_exp(unused_self) } + + /// Deprecated: use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn min_10_exp(unused_self: Option) -> int { num::Float::min_10_exp(unused_self) } + + /// Deprecated: use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn max_10_exp(unused_self: Option) -> int { num::Float::max_10_exp(unused_self) } + + /// Returns the smallest finite value that this type can represent. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x: f64 = Float::min_value(); + /// + /// assert_eq!(x, f64::MIN); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn min_value() -> f32 { num::Float::min_value() } + + /// Returns the smallest normalized positive number that this type can represent. + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn min_pos_value(unused_self: Option) -> f32 { num::Float::min_pos_value(unused_self) } + + /// Returns the largest finite value that this type can represent. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x: f64 = Float::max_value(); + /// assert_eq!(x, f64::MAX); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn max_value() -> f32 { num::Float::max_value() } + + /// Returns `true` if this value is `NaN` and false otherwise. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan = f64::NAN; + /// let f = 7.0; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_nan(self) -> bool { num::Float::is_nan(self) } + + /// Returns `true` if this value is positive infinity or negative infinity and + /// false otherwise. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf: f32 = Float::infinity(); + /// let neg_inf: f32 = Float::neg_infinity(); + /// let nan: f32 = f32::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) } + + /// Returns `true` if this number is neither infinite nor `NaN`. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf: f32 = Float::infinity(); + /// let neg_inf: f32 = Float::neg_infinity(); + /// let nan: f32 = f32::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_finite(self) -> bool { num::Float::is_finite(self) } + + /// Returns `true` if the number is neither zero, infinite, + /// [subnormal][subnormal], or `NaN`. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 + /// let max = f32::MAX; + /// let lower_than_min = 1.0e-40_f32; + /// let zero = 0.0f32; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f32::NAN.is_normal()); + /// assert!(!f32::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// ``` + /// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_normal(self) -> bool { num::Float::is_normal(self) } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// use std::num::{Float, FpCategory}; + /// use std::f32; + /// + /// let num = 12.4f32; + /// let inf = f32::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn classify(self) -> FpCategory { num::Float::classify(self) } + + /// Returns the mantissa, base 2 exponent, and sign as integers, respectively. + /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`. + /// The floating point encoding is documented in the [Reference][floating-point]. + /// + /// ``` + /// use std::num::Float; + /// + /// let num = 2.0f32; + /// + /// // (8388608, -22, 1) + /// let (mantissa, exponent, sign) = num.integer_decode(); + /// let sign_f = sign as f32; + /// let mantissa_f = mantissa as f32; + /// let exponent_f = num.powf(exponent as f32); + /// + /// // 1 * 8388608 * 2^(-22) == 2 + /// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + /// [floating-point]: ../../../../../reference.html#machine-types + #[unstable(feature = "std_misc", reason = "signature is undecided")] + #[inline] + pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) } + + /// Returns the largest integer less than or equal to a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.99; + /// let g = 3.0; + /// + /// assert_eq!(f.floor(), 3.0); + /// assert_eq!(g.floor(), 3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn floor(self) -> f32 { num::Float::floor(self) } + + /// Returns the smallest integer greater than or equal to a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.01; + /// let g = 4.0; + /// + /// assert_eq!(f.ceil(), 4.0); + /// assert_eq!(g.ceil(), 4.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ceil(self) -> f32 { num::Float::ceil(self) } + + /// Returns the nearest integer to a number. Round half-way cases away from + /// `0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.3; + /// let g = -3.3; + /// + /// assert_eq!(f.round(), 3.0); + /// assert_eq!(g.round(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn round(self) -> f32 { num::Float::round(self) } + + /// Return the integer part of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.3; + /// let g = -3.7; + /// + /// assert_eq!(f.trunc(), 3.0); + /// assert_eq!(g.trunc(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn trunc(self) -> f32 { num::Float::trunc(self) } + + /// Returns the fractional part of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 3.5; + /// let y = -3.5; + /// let abs_difference_x = (x.fract() - 0.5).abs(); + /// let abs_difference_y = (y.fract() - (-0.5)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn fract(self) -> f32 { num::Float::fract(self) } + + /// Computes the absolute value of `self`. Returns `Float::nan()` if the + /// number is `Float::nan()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = 3.5; + /// let y = -3.5; + /// + /// let abs_difference_x = (x.abs() - x).abs(); + /// let abs_difference_y = (y.abs() - (-y)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// + /// assert!(f64::NAN.abs().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn abs(self) -> f32 { num::Float::abs(self) } + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()` + /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()` + /// - `Float::nan()` if the number is `Float::nan()` + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = 3.5; + /// + /// assert_eq!(f.signum(), 1.0); + /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0); + /// + /// assert!(f64::NAN.signum().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn signum(self) -> f32 { num::Float::signum(self) } + + /// Returns `true` if `self` is positive, including `+0.0` and + /// `Float::infinity()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan: f64 = f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// assert!(f.is_positive()); + /// assert!(!g.is_positive()); + /// // Requires both tests to determine if is `NaN` + /// assert!(!nan.is_positive() && !nan.is_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_positive(self) -> bool { num::Float::is_positive(self) } + + /// Returns `true` if `self` is negative, including `-0.0` and + /// `Float::neg_infinity()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan = f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// assert!(!f.is_negative()); + /// assert!(g.is_negative()); + /// // Requires both tests to determine if is `NaN`. + /// assert!(!nan.is_positive() && !nan.is_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_negative(self) -> bool { num::Float::is_negative(self) } + + /// Fused multiply-add. Computes `(self * a) + b` with only one rounding + /// error. This produces a more accurate result with better performance than + /// a separate multiplication operation followed by an add. + /// + /// ``` + /// use std::num::Float; + /// + /// let m = 10.0; + /// let x = 4.0; + /// let b = 60.0; + /// + /// // 100.0 + /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn mul_add(self, a: f32, b: f32) -> f32 { num::Float::mul_add(self, a, b) } + + /// Take the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn recip(self) -> f32 { num::Float::recip(self) } + + /// Raise a number to an integer power. + /// + /// Using this function is generally faster than using `powf` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.powi(2) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) } + + /// Raise a number to a floating point power. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powf(self, n: f32) -> f32 { num::Float::powf(self, n) } + + /// Take the square root of a number. + /// + /// Returns NaN if `self` is a negative number. + /// + /// ``` + /// use std::num::Float; + /// + /// let positive = 4.0; + /// let negative = -4.0; + /// + /// let abs_difference = (positive.sqrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// assert!(negative.sqrt().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sqrt(self) -> f32 { num::Float::sqrt(self) } + + + /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 4.0; + /// + /// let abs_difference = (f.rsqrt() - 0.5).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn rsqrt(self) -> f32 { num::Float::rsqrt(self) } + + /// Returns `e^(self)`, (the exponential function). + /// + /// ``` + /// use std::num::Float; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp(self) -> f32 { num::Float::exp(self) } + + /// Returns `2^(self)`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 2.0; + /// + /// // 2^2 - 4 == 0 + /// let abs_difference = (f.exp2() - 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp2(self) -> f32 { num::Float::exp2(self) } + + /// Returns the natural logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ln(self) -> f32 { num::Float::ln(self) } + + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// ``` + /// use std::num::Float; + /// + /// let ten = 10.0; + /// let two = 2.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs(); + /// + /// // log2(2) - 1 == 0 + /// let abs_difference_2 = (two.log(2.0) - 1.0).abs(); + /// + /// assert!(abs_difference_10 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log(self, base: f32) -> f32 { num::Float::log(self, base) } + + /// Returns the base 2 logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let two = 2.0; + /// + /// // log2(2) - 1 == 0 + /// let abs_difference = (two.log2() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log2(self) -> f32 { num::Float::log2(self) } + + /// Returns the base 10 logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let ten = 10.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference = (ten.log10() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log10(self) -> f32 { num::Float::log10(self) } + + /// Convert radians to degrees. + /// + /// ``` + /// use std::num::Float; + /// use std::f64::consts; + /// + /// let angle = consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "desirability is unclear")] + #[inline] + pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) } + + /// Convert degrees to radians. + /// + /// ``` + /// use std::num::Float; + /// use std::f64::consts; + /// + /// let angle = 180.0; + /// + /// let abs_difference = (angle.to_radians() - consts::PI).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "desirability is unclear")] + #[inline] + pub fn to_radians(self) -> f32 { num::Float::to_radians(self) } + + /// Constructs a floating point number of `x*2^exp`. + /// + /// ``` + /// use std::num::Float; + /// + /// // 3*2^2 - 12 == 0 + /// let abs_difference = (Float::ldexp(3.0, 2) - 12.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn ldexp(x: f32, exp: int) -> f32 { + unsafe { cmath::ldexpf(x, exp as c_int) } + } + + /// Breaks the number into a normalized fraction and a base-2 exponent, + /// satisfying: + /// + /// * `self = x * 2^exp` + /// * `0.5 <= abs(x) < 1.0` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 4.0; + /// + /// // (1/2)*2^3 -> 1 * 8/2 -> 4.0 + /// let f = x.frexp(); + /// let abs_difference_0 = (f.0 - 0.5).abs(); + /// let abs_difference_1 = (f.1 as f64 - 3.0).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_1 < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn frexp(self) -> (f32, int) { + unsafe { + let mut exp = 0; + let x = cmath::frexpf(self, &mut exp); + (x, exp as int) + } + } + + /// Returns the next representable floating-point value in the direction of + /// `other`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0f32; + /// + /// let abs_diff = (x.next_after(2.0) - 1.00000011920928955078125_f32).abs(); + /// + /// assert!(abs_diff < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn next_after(self, other: f32) -> f32 { + unsafe { cmath::nextafterf(self, other) } + } + + /// Returns the maximum of the two numbers. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.max(y), y); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn max(self, other: f32) -> f32 { + unsafe { cmath::fmaxf(self, other) } + } + + /// Returns the minimum of the two numbers. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.min(y), x); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn min(self, other: f32) -> f32 { + unsafe { cmath::fminf(self, other) } + } + + /// The positive difference of two numbers. + /// + /// * If `self <= other`: `0:0` + /// * Else: `self - other` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 3.0; + /// let y = -3.0; + /// + /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs(); + /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn abs_sub(self, other: f32) -> f32 { + unsafe { cmath::fdimf(self, other) } + } + + /// Take the cubic root of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 8.0; + /// + /// // x^(1/3) - 2 == 0 + /// let abs_difference = (x.cbrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn cbrt(self) -> f32 { + unsafe { cmath::cbrtf(self) } + } + + /// Calculate the length of the hypotenuse of a right-angle triangle given + /// legs of length `x` and `y`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let y = 3.0; + /// + /// // sqrt(x^2 + y^2) + /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn hypot(self, other: f32) -> f32 { + unsafe { cmath::hypotf(self, other) } + } + + /// Computes the sine of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/2.0; + /// + /// let abs_difference = (x.sin() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin(self) -> f32 { + unsafe { intrinsics::sinf32(self) } + } + + /// Computes the cosine of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = 2.0*f64::consts::PI; + /// + /// let abs_difference = (x.cos() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cos(self) -> f32 { + unsafe { intrinsics::cosf32(self) } + } + + /// Computes the tangent of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let abs_difference = (x.tan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-14); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tan(self) -> f32 { + unsafe { cmath::tanf(self) } + } + + /// Computes the arcsine of a number. Return value is in radians in + /// the range [-pi/2, pi/2] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = f64::consts::PI / 2.0; + /// + /// // asin(sin(pi/2)) + /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asin(self) -> f32 { + unsafe { cmath::asinf(self) } + } + + /// Computes the arccosine of a number. Return value is in radians in + /// the range [0, pi] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = f64::consts::PI / 4.0; + /// + /// // acos(cos(pi/4)) + /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acos(self) -> f32 { + unsafe { cmath::acosf(self) } + } + + /// Computes the arctangent of a number. Return value is in radians in the + /// range [-pi/2, pi/2]; + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 1.0; + /// + /// // atan(tan(1)) + /// let abs_difference = (f.tan().atan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan(self) -> f32 { + unsafe { cmath::atanf(self) } + } + + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// + /// * `x = 0`, `y = 0`: `0` + /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` + /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` + /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let pi = f64::consts::PI; + /// // All angles from horizontal right (+x) + /// // 45 deg counter-clockwise + /// let x1 = 3.0; + /// let y1 = -3.0; + /// + /// // 135 deg clockwise + /// let x2 = -3.0; + /// let y2 = 3.0; + /// + /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// + /// assert!(abs_difference_1 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan2(self, other: f32) -> f32 { + unsafe { cmath::atan2f(self, other) } + } + + /// Simultaneously computes the sine and cosine of the number, `x`. Returns + /// `(sin(x), cos(x))`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let f = x.sin_cos(); + /// + /// let abs_difference_0 = (f.0 - x.sin()).abs(); + /// let abs_difference_1 = (f.1 - x.cos()).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_0 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin_cos(self) -> (f32, f32) { + (self.sin(), self.cos()) + } + + /// Returns `e^(self) - 1` in a way that is accurate even if the + /// number is close to zero. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 7.0; + /// + /// // e^(ln(7)) - 1 + /// let abs_difference = (x.ln().exp_m1() - 6.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn exp_m1(self) -> f32 { + unsafe { cmath::expm1f(self) } + } + + /// Returns `ln(1+n)` (natural logarithm) more accurately than if + /// the operations were performed separately. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::E - 1.0; + /// + /// // ln(1 + (e - 1)) == ln(e) == 1 + /// let abs_difference = (x.ln_1p() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn ln_1p(self) -> f32 { + unsafe { cmath::log1pf(self) } + } + + /// Hyperbolic sine function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.sinh(); + /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` + /// let g = (e*e - 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sinh(self) -> f32 { + unsafe { cmath::sinhf(self) } + } + + /// Hyperbolic cosine function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// let f = x.cosh(); + /// // Solving cosh() at 1 gives this result + /// let g = (e*e + 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// // Same result + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cosh(self) -> f32 { + unsafe { cmath::coshf(self) } + } + + /// Hyperbolic tangent function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.tanh(); + /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` + /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tanh(self) -> f32 { + unsafe { cmath::tanhf(self) } + } + + /// Inverse hyperbolic sine function. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let f = x.sinh().asinh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asinh(self) -> f32 { + match self { + NEG_INFINITY => NEG_INFINITY, + x => (x + ((x * x) + 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic cosine function. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let f = x.cosh().acosh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acosh(self) -> f32 { + match self { + x if x < 1.0 => Float::nan(), + x => (x + ((x * x) - 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic tangent function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let f = e.tanh().atanh(); + /// + /// let abs_difference = (f - e).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atanh(self) -> f32 { + 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() + } +} + // // Section: String Conversions // diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 95065b59678c9..f3978cae48510 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -366,6 +366,1235 @@ impl Float for f64 { } } +#[cfg(not(stage0))] +#[cfg(not(test))] +#[lang = "f64"] +#[stable(feature = "rust1", since = "1.0.0")] +impl f64 { + // inlined methods from `num::Float` + /// Returns the `NaN` value. + /// + /// ``` + /// use std::num::Float; + /// + /// let nan: f32 = Float::nan(); + /// + /// assert!(nan.is_nan()); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn nan() -> f64 { num::Float::nan() } + + /// Returns the infinite value. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let infinity: f32 = Float::infinity(); + /// + /// assert!(infinity.is_infinite()); + /// assert!(!infinity.is_finite()); + /// assert!(infinity > f32::MAX); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn infinity() -> f64 { num::Float::infinity() } + + /// Returns the negative infinite value. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let neg_infinity: f32 = Float::neg_infinity(); + /// + /// assert!(neg_infinity.is_infinite()); + /// assert!(!neg_infinity.is_finite()); + /// assert!(neg_infinity < f32::MIN); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn neg_infinity() -> f64 { num::Float::neg_infinity() } + + /// Returns `0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let inf: f32 = Float::infinity(); + /// let zero: f32 = Float::zero(); + /// let neg_zero: f32 = Float::neg_zero(); + /// + /// assert_eq!(zero, neg_zero); + /// assert_eq!(7.0f32/inf, zero); + /// assert_eq!(zero * 10.0, zero); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn zero() -> f64 { num::Float::zero() } + + /// Returns `-0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let inf: f32 = Float::infinity(); + /// let zero: f32 = Float::zero(); + /// let neg_zero: f32 = Float::neg_zero(); + /// + /// assert_eq!(zero, neg_zero); + /// assert_eq!(7.0f32/inf, zero); + /// assert_eq!(zero * 10.0, zero); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn neg_zero() -> f64 { num::Float::neg_zero() } + + /// Returns `1.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let one: f32 = Float::one(); + /// + /// assert_eq!(one, 1.0f32); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn one() -> f64 { num::Float::one() } + + // FIXME (#5527): These should be associated constants + + /// Deprecated: use `std::f32::MANTISSA_DIGITS` or `std::f64::MANTISSA_DIGITS` + /// instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MANTISSA_DIGITS` or \ + `std::f64::MANTISSA_DIGITS` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn mantissa_digits(unused_self: Option) -> uint { + num::Float::mantissa_digits(unused_self) + } + + /// Deprecated: use `std::f32::DIGITS` or `std::f64::DIGITS` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn digits(unused_self: Option) -> uint { num::Float::digits(unused_self) } + + /// Deprecated: use `std::f32::EPSILON` or `std::f64::EPSILON` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn epsilon() -> f64 { num::Float::epsilon() } + + /// Deprecated: use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn min_exp(unused_self: Option) -> int { num::Float::min_exp(unused_self) } + + /// Deprecated: use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn max_exp(unused_self: Option) -> int { num::Float::max_exp(unused_self) } + + /// Deprecated: use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn min_10_exp(unused_self: Option) -> int { num::Float::min_10_exp(unused_self) } + + /// Deprecated: use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", + reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")] + #[allow(deprecated)] + #[inline] + pub fn max_10_exp(unused_self: Option) -> int { num::Float::max_10_exp(unused_self) } + + /// Returns the smallest finite value that this type can represent. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x: f64 = Float::min_value(); + /// + /// assert_eq!(x, f64::MIN); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn min_value() -> f64 { num::Float::min_value() } + + /// Returns the smallest normalized positive number that this type can represent. + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn min_pos_value(unused_self: Option) -> f64 { num::Float::min_pos_value(unused_self) } + + /// Returns the largest finite value that this type can represent. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x: f64 = Float::max_value(); + /// assert_eq!(x, f64::MAX); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + #[allow(deprecated)] + pub fn max_value() -> f64 { num::Float::max_value() } + + /// Returns `true` if this value is `NaN` and false otherwise. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan = f64::NAN; + /// let f = 7.0; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_nan(self) -> bool { num::Float::is_nan(self) } + + /// Returns `true` if this value is positive infinity or negative infinity and + /// false otherwise. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf: f32 = Float::infinity(); + /// let neg_inf: f32 = Float::neg_infinity(); + /// let nan: f32 = f32::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) } + + /// Returns `true` if this number is neither infinite nor `NaN`. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf: f32 = Float::infinity(); + /// let neg_inf: f32 = Float::neg_infinity(); + /// let nan: f32 = f32::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// ``` + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_finite(self) -> bool { num::Float::is_finite(self) } + + /// Returns `true` if the number is neither zero, infinite, + /// [subnormal][subnormal], or `NaN`. + /// + /// ``` + /// use std::num::Float; + /// use std::f32; + /// + /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 + /// let max = f32::MAX; + /// let lower_than_min = 1.0e-40_f32; + /// let zero = 0.0f32; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f32::NAN.is_normal()); + /// assert!(!f32::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// ``` + /// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number + #[unstable(feature = "std_misc", reason = "position is undecided")] + #[inline] + pub fn is_normal(self) -> bool { num::Float::is_normal(self) } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// use std::num::{Float, FpCategory}; + /// use std::f32; + /// + /// let num = 12.4f32; + /// let inf = f32::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn classify(self) -> FpCategory { num::Float::classify(self) } + + /// Returns the mantissa, base 2 exponent, and sign as integers, respectively. + /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`. + /// The floating point encoding is documented in the [Reference][floating-point]. + /// + /// ``` + /// use std::num::Float; + /// + /// let num = 2.0f32; + /// + /// // (8388608, -22, 1) + /// let (mantissa, exponent, sign) = num.integer_decode(); + /// let sign_f = sign as f32; + /// let mantissa_f = mantissa as f32; + /// let exponent_f = num.powf(exponent as f32); + /// + /// // 1 * 8388608 * 2^(-22) == 2 + /// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + /// [floating-point]: ../../../../../reference.html#machine-types + #[unstable(feature = "std_misc", reason = "signature is undecided")] + #[inline] + pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) } + + /// Returns the largest integer less than or equal to a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.99; + /// let g = 3.0; + /// + /// assert_eq!(f.floor(), 3.0); + /// assert_eq!(g.floor(), 3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn floor(self) -> f64 { num::Float::floor(self) } + + /// Returns the smallest integer greater than or equal to a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.01; + /// let g = 4.0; + /// + /// assert_eq!(f.ceil(), 4.0); + /// assert_eq!(g.ceil(), 4.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ceil(self) -> f64 { num::Float::ceil(self) } + + /// Returns the nearest integer to a number. Round half-way cases away from + /// `0.0`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.3; + /// let g = -3.3; + /// + /// assert_eq!(f.round(), 3.0); + /// assert_eq!(g.round(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn round(self) -> f64 { num::Float::round(self) } + + /// Return the integer part of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 3.3; + /// let g = -3.7; + /// + /// assert_eq!(f.trunc(), 3.0); + /// assert_eq!(g.trunc(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn trunc(self) -> f64 { num::Float::trunc(self) } + + /// Returns the fractional part of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 3.5; + /// let y = -3.5; + /// let abs_difference_x = (x.fract() - 0.5).abs(); + /// let abs_difference_y = (y.fract() - (-0.5)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn fract(self) -> f64 { num::Float::fract(self) } + + /// Computes the absolute value of `self`. Returns `Float::nan()` if the + /// number is `Float::nan()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = 3.5; + /// let y = -3.5; + /// + /// let abs_difference_x = (x.abs() - x).abs(); + /// let abs_difference_y = (y.abs() - (-y)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// + /// assert!(f64::NAN.abs().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn abs(self) -> f64 { num::Float::abs(self) } + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()` + /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()` + /// - `Float::nan()` if the number is `Float::nan()` + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = 3.5; + /// + /// assert_eq!(f.signum(), 1.0); + /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0); + /// + /// assert!(f64::NAN.signum().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn signum(self) -> f64 { num::Float::signum(self) } + + /// Returns `true` if `self` is positive, including `+0.0` and + /// `Float::infinity()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan: f64 = f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// assert!(f.is_positive()); + /// assert!(!g.is_positive()); + /// // Requires both tests to determine if is `NaN` + /// assert!(!nan.is_positive() && !nan.is_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_positive(self) -> bool { num::Float::is_positive(self) } + + /// Returns `true` if `self` is negative, including `-0.0` and + /// `Float::neg_infinity()`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let nan = f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// assert!(!f.is_negative()); + /// assert!(g.is_negative()); + /// // Requires both tests to determine if is `NaN`. + /// assert!(!nan.is_positive() && !nan.is_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_negative(self) -> bool { num::Float::is_negative(self) } + + /// Fused multiply-add. Computes `(self * a) + b` with only one rounding + /// error. This produces a more accurate result with better performance than + /// a separate multiplication operation followed by an add. + /// + /// ``` + /// use std::num::Float; + /// + /// let m = 10.0; + /// let x = 4.0; + /// let b = 60.0; + /// + /// // 100.0 + /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn mul_add(self, a: f64, b: f64) -> f64 { num::Float::mul_add(self, a, b) } + + /// Take the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn recip(self) -> f64 { num::Float::recip(self) } + + /// Raise a number to an integer power. + /// + /// Using this function is generally faster than using `powf` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.powi(2) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) } + + /// Raise a number to a floating point power. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powf(self, n: f64) -> f64 { num::Float::powf(self, n) } + + /// Take the square root of a number. + /// + /// Returns NaN if `self` is a negative number. + /// + /// ``` + /// use std::num::Float; + /// + /// let positive = 4.0; + /// let negative = -4.0; + /// + /// let abs_difference = (positive.sqrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// assert!(negative.sqrt().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sqrt(self) -> f64 { num::Float::sqrt(self) } + + /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 4.0; + /// + /// let abs_difference = (f.rsqrt() - 0.5).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn rsqrt(self) -> f64 { num::Float::rsqrt(self) } + + /// Returns `e^(self)`, (the exponential function). + /// + /// ``` + /// use std::num::Float; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp(self) -> f64 { num::Float::exp(self) } + + /// Returns `2^(self)`. + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 2.0; + /// + /// // 2^2 - 4 == 0 + /// let abs_difference = (f.exp2() - 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp2(self) -> f64 { num::Float::exp2(self) } + + /// Returns the natural logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ln(self) -> f64 { num::Float::ln(self) } + + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// ``` + /// use std::num::Float; + /// + /// let ten = 10.0; + /// let two = 2.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs(); + /// + /// // log2(2) - 1 == 0 + /// let abs_difference_2 = (two.log(2.0) - 1.0).abs(); + /// + /// assert!(abs_difference_10 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log(self, base: f64) -> f64 { num::Float::log(self, base) } + + /// Returns the base 2 logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let two = 2.0; + /// + /// // log2(2) - 1 == 0 + /// let abs_difference = (two.log2() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log2(self) -> f64 { num::Float::log2(self) } + + /// Returns the base 10 logarithm of the number. + /// + /// ``` + /// use std::num::Float; + /// + /// let ten = 10.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference = (ten.log10() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log10(self) -> f64 { num::Float::log10(self) } + + /// Convert radians to degrees. + /// + /// ``` + /// use std::num::Float; + /// use std::f64::consts; + /// + /// let angle = consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "desirability is unclear")] + #[inline] + pub fn to_degrees(self) -> f64 { num::Float::to_degrees(self) } + + /// Convert degrees to radians. + /// + /// ``` + /// use std::num::Float; + /// use std::f64::consts; + /// + /// let angle = 180.0; + /// + /// let abs_difference = (angle.to_radians() - consts::PI).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "desirability is unclear")] + #[inline] + pub fn to_radians(self) -> f64 { num::Float::to_radians(self) } + + /// Constructs a floating point number of `x*2^exp`. + /// + /// ``` + /// use std::num::Float; + /// + /// // 3*2^2 - 12 == 0 + /// let abs_difference = (Float::ldexp(3.0, 2) - 12.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn ldexp(x: f64, exp: int) -> f64 { + unsafe { cmath::ldexp(x, exp as c_int) } + } + + /// Breaks the number into a normalized fraction and a base-2 exponent, + /// satisfying: + /// + /// * `self = x * 2^exp` + /// * `0.5 <= abs(x) < 1.0` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 4.0; + /// + /// // (1/2)*2^3 -> 1 * 8/2 -> 4.0 + /// let f = x.frexp(); + /// let abs_difference_0 = (f.0 - 0.5).abs(); + /// let abs_difference_1 = (f.1 as f64 - 3.0).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_1 < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn frexp(self) -> (f64, int) { + unsafe { + let mut exp = 0; + let x = cmath::frexp(self, &mut exp); + (x, exp as int) + } + } + + /// Returns the next representable floating-point value in the direction of + /// `other`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0f32; + /// + /// let abs_diff = (x.next_after(2.0) - 1.00000011920928955078125_f32).abs(); + /// + /// assert!(abs_diff < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn next_after(self, other: f64) -> f64 { + unsafe { cmath::nextafter(self, other) } + } + + /// Returns the maximum of the two numbers. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.max(y), y); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn max(self, other: f64) -> f64 { + unsafe { cmath::fmax(self, other) } + } + + /// Returns the minimum of the two numbers. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.min(y), x); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn min(self, other: f64) -> f64 { + unsafe { cmath::fmin(self, other) } + } + + /// The positive difference of two numbers. + /// + /// * If `self <= other`: `0:0` + /// * Else: `self - other` + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 3.0; + /// let y = -3.0; + /// + /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs(); + /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn abs_sub(self, other: f64) -> f64 { + unsafe { cmath::fdim(self, other) } + } + + /// Take the cubic root of a number. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 8.0; + /// + /// // x^(1/3) - 2 == 0 + /// let abs_difference = (x.cbrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn cbrt(self) -> f64 { + unsafe { cmath::cbrt(self) } + } + + /// Calculate the length of the hypotenuse of a right-angle triangle given + /// legs of length `x` and `y`. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 2.0; + /// let y = 3.0; + /// + /// // sqrt(x^2 + y^2) + /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn hypot(self, other: f64) -> f64 { + unsafe { cmath::hypot(self, other) } + } + + /// Computes the sine of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/2.0; + /// + /// let abs_difference = (x.sin() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin(self) -> f64 { + unsafe { intrinsics::sinf64(self) } + } + + /// Computes the cosine of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = 2.0*f64::consts::PI; + /// + /// let abs_difference = (x.cos() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cos(self) -> f64 { + unsafe { intrinsics::cosf64(self) } + } + + /// Computes the tangent of a number (in radians). + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let abs_difference = (x.tan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-14); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tan(self) -> f64 { + unsafe { cmath::tan(self) } + } + + /// Computes the arcsine of a number. Return value is in radians in + /// the range [-pi/2, pi/2] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = f64::consts::PI / 2.0; + /// + /// // asin(sin(pi/2)) + /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asin(self) -> f64 { + unsafe { cmath::asin(self) } + } + + /// Computes the arccosine of a number. Return value is in radians in + /// the range [0, pi] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let f = f64::consts::PI / 4.0; + /// + /// // acos(cos(pi/4)) + /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acos(self) -> f64 { + unsafe { cmath::acos(self) } + } + + /// Computes the arctangent of a number. Return value is in radians in the + /// range [-pi/2, pi/2]; + /// + /// ``` + /// use std::num::Float; + /// + /// let f = 1.0; + /// + /// // atan(tan(1)) + /// let abs_difference = (f.tan().atan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan(self) -> f64 { + unsafe { cmath::atan(self) } + } + + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// + /// * `x = 0`, `y = 0`: `0` + /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` + /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` + /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let pi = f64::consts::PI; + /// // All angles from horizontal right (+x) + /// // 45 deg counter-clockwise + /// let x1 = 3.0; + /// let y1 = -3.0; + /// + /// // 135 deg clockwise + /// let x2 = -3.0; + /// let y2 = 3.0; + /// + /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// + /// assert!(abs_difference_1 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan2(self, other: f64) -> f64 { + unsafe { cmath::atan2(self, other) } + } + + /// Simultaneously computes the sine and cosine of the number, `x`. Returns + /// `(sin(x), cos(x))`. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let f = x.sin_cos(); + /// + /// let abs_difference_0 = (f.0 - x.sin()).abs(); + /// let abs_difference_1 = (f.1 - x.cos()).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_0 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin_cos(self) -> (f64, f64) { + (self.sin(), self.cos()) + } + + /// Returns `e^(self) - 1` in a way that is accurate even if the + /// number is close to zero. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 7.0; + /// + /// // e^(ln(7)) - 1 + /// let abs_difference = (x.ln().exp_m1() - 6.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn exp_m1(self) -> f64 { + unsafe { cmath::expm1(self) } + } + + /// Returns `ln(1+n)` (natural logarithm) more accurately than if + /// the operations were performed separately. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let x = f64::consts::E - 1.0; + /// + /// // ln(1 + (e - 1)) == ln(e) == 1 + /// let abs_difference = (x.ln_1p() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", reason = "may be renamed")] + #[inline] + pub fn ln_1p(self) -> f64 { + unsafe { cmath::log1p(self) } + } + + /// Hyperbolic sine function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.sinh(); + /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` + /// let g = (e*e - 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sinh(self) -> f64 { + unsafe { cmath::sinh(self) } + } + + /// Hyperbolic cosine function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// let f = x.cosh(); + /// // Solving cosh() at 1 gives this result + /// let g = (e*e + 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// // Same result + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cosh(self) -> f64 { + unsafe { cmath::cosh(self) } + } + + /// Hyperbolic tangent function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.tanh(); + /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` + /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tanh(self) -> f64 { + unsafe { cmath::tanh(self) } + } + + /// Inverse hyperbolic sine function. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let f = x.sinh().asinh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asinh(self) -> f64 { + match self { + NEG_INFINITY => NEG_INFINITY, + x => (x + ((x * x) + 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic cosine function. + /// + /// ``` + /// use std::num::Float; + /// + /// let x = 1.0; + /// let f = x.cosh().acosh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acosh(self) -> f64 { + match self { + x if x < 1.0 => Float::nan(), + x => (x + ((x * x) - 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic tangent function. + /// + /// ``` + /// use std::num::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let f = e.tanh().atanh(); + /// + /// let abs_difference = (f - e).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atanh(self) -> f64 { + 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() + } +} + // // Section: String Conversions // diff --git a/src/libstd/num/float_macros.rs b/src/libstd/num/float_macros.rs index 2b730cd6f9ad8..ece7af9c1523d 100644 --- a/src/libstd/num/float_macros.rs +++ b/src/libstd/num/float_macros.rs @@ -11,6 +11,7 @@ #![unstable(feature = "std_misc")] #![doc(hidden)] +#[cfg(stage0)] macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ use num::Float; @@ -19,3 +20,12 @@ macro_rules! assert_approx_eq { "{} is not approximately equal to {}", *a, *b); }) } + +#[cfg(not(stage0))] +macro_rules! assert_approx_eq { + ($a:expr, $b:expr) => ({ + let (a, b) = (&$a, &$b); + assert!((*a - *b).abs() < 1.0e-6, + "{} is not approximately equal to {}", *a, *b); + }) +} diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1b51b5155998d..bf2b2c0afe6c3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -78,6 +78,7 @@ use owned_slice::OwnedSlice; use std::collections::HashSet; use std::io::prelude::*; use std::mem; +#[cfg(stage0)] use std::num::Float; use std::path::{Path, PathBuf}; use std::rc::Rc; From b65ebc4094589a65f76a49a790321f1417c67267 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 13 Mar 2015 19:44:02 -0500 Subject: [PATCH 15/15] better document the hacks required to test libcollections --- src/libcollections/macros.rs | 6 +- src/libcollections/slice.rs | 211 +++++++++++++++++++---------------- src/libcollections/string.rs | 10 +- src/libcollections/vec.rs | 9 +- 4 files changed, 133 insertions(+), 103 deletions(-) diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index be3d8f8dbb63d..3c7326dbd8f04 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -84,8 +84,10 @@ macro_rules! vec { ($($x:expr,)*) => (vec![$($x),*]) } -// HACK: `impl [T]` is not available in cfg(test), use `::slice::into_vec`, instead of -// `<[T]>::to_vec` +// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is required for this +// macro definition, is not available. Instead use the `slice::into_vec` function which is only +// available with cfg(test) +// NB see the slice::hack module in slice.rs for more information #[cfg(not(stage0))] #[cfg(test)] macro_rules! vec { diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index dafe0edbf32c7..dd9c265874467 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1083,30 +1083,113 @@ impl SliceExt for [T] { } } -// HACK: With cfg(test) `impl [T]` is not available, these three functions are actually methods -// that are in `impl [T]` but not in `core::slice::SliceExt` - this is only need for testing +// HACK(japaric) needed for the implementation of `vec!` macro during testing +// NB see the hack module in this file for more details +#[cfg(not(stage0))] #[cfg(test)] -pub fn into_vec(mut b: Box<[T]>) -> Vec { - unsafe { - let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len()); - mem::forget(b); - xs - } -} +pub use self::hack::into_vec; +// HACK(japaric) needed for the implementation of `Vec::clone` during testing +// NB see the hack module in this file for more details +#[cfg(not(stage0))] #[cfg(test)] -pub fn permutations(s: &[T]) -> Permutations where T: Clone { - Permutations{ - swaps: ElementSwaps::new(s.len()), - v: ::slice::to_vec(s), +pub use self::hack::to_vec; + +// HACK(japaric): With cfg(test) `impl [T]` is not available, these three functions are actually +// methods that are in `impl [T]` but not in `core::slice::SliceExt` - we need to supply these +// functions for the `test_permutations` test +#[cfg(not(stage0))] +mod hack { + use alloc::boxed::Box; + use core::clone::Clone; + #[cfg(test)] + use core::iter::{Iterator, IteratorExt}; + use core::mem; + #[cfg(test)] + use core::option::Option::{Some, None}; + + #[cfg(test)] + use string::ToString; + use vec::Vec; + + use super::{ElementSwaps, Permutations}; + + pub fn into_vec(mut b: Box<[T]>) -> Vec { + unsafe { + let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len()); + mem::forget(b); + xs + } } -} -#[cfg(test)] -pub fn to_vec(s: &[T]) -> Vec where T: Clone { - let mut vector = Vec::with_capacity(s.len()); - vector.push_all(s); - vector + pub fn permutations(s: &[T]) -> Permutations where T: Clone { + Permutations{ + swaps: ElementSwaps::new(s.len()), + v: to_vec(s), + } + } + + #[inline] + pub fn to_vec(s: &[T]) -> Vec where T: Clone { + let mut vector = Vec::with_capacity(s.len()); + vector.push_all(s); + vector + } + + // NB we can remove this hack if we move this test to libcollectionstest - but that can't be + // done right now because the test needs access to the private fields of Permutations + #[test] + fn test_permutations() { + { + let v: [i32; 0] = []; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 1); + assert_eq!(max_opt.unwrap(), 1); + assert_eq!(it.next(), Some(to_vec(&v))); + assert_eq!(it.next(), None); + } + { + let v = ["Hello".to_string()]; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 1); + assert_eq!(max_opt.unwrap(), 1); + assert_eq!(it.next(), Some(to_vec(&v))); + assert_eq!(it.next(), None); + } + { + let v = [1, 2, 3]; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 3*2); + assert_eq!(max_opt.unwrap(), 3*2); + assert_eq!(it.next().unwrap(), [1,2,3]); + assert_eq!(it.next().unwrap(), [1,3,2]); + assert_eq!(it.next().unwrap(), [3,1,2]); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 3); + assert_eq!(max_opt.unwrap(), 3); + assert_eq!(it.next().unwrap(), [3,2,1]); + assert_eq!(it.next().unwrap(), [2,3,1]); + assert_eq!(it.next().unwrap(), [2,1,3]); + assert_eq!(it.next(), None); + } + { + // check that we have N! permutations + let v = ['A', 'B', 'C', 'D', 'E', 'F']; + let mut amt = 0; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + for _perm in it.by_ref() { + amt += 1; + } + assert_eq!(amt, it.swaps.swaps_made); + assert_eq!(amt, min_size); + assert_eq!(amt, 2 * 3 * 4 * 5 * 6); + assert_eq!(amt, max_opt.unwrap()); + } + } } #[cfg(not(stage0))] @@ -1715,9 +1798,8 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn to_vec(&self) -> Vec where T: Clone { - let mut vector = Vec::with_capacity(self.len()); - vector.push_all(self); - vector + // NB see hack module in this file + hack::to_vec(self) } /// Creates an iterator that yields every possible permutation of the @@ -1745,11 +1827,10 @@ impl [T] { /// assert_eq!(Some(vec![3, 1, 2]), perms.next()); /// ``` #[unstable(feature = "collections")] + #[inline] pub fn permutations(&self) -> Permutations where T: Clone { - Permutations{ - swaps: ElementSwaps::new(self.len()), - v: self.to_vec(), - } + // NB see hack module in this file + hack::permutations(self) } /// Copies as many elements from `src` as it can into `self` (the @@ -1931,12 +2012,10 @@ impl [T] { /// Convert `self` into a vector without clones or allocation. #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_vec(mut self: Box) -> Vec { - unsafe { - let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); - mem::forget(self); - xs - } + #[inline] + pub fn into_vec(self: Box) -> Vec { + // NB see hack module in this file + hack::into_vec(self) } } @@ -2052,10 +2131,12 @@ impl ToOwned for [T] { #[cfg(not(test))] fn to_owned(&self) -> Vec { self.to_vec() } - // HACK: `impl [T]` is not available in cfg(test), use `::slice::to_vec` instead of - // `<[T]>::to_vec` + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec`, which is required for this method + // definition, is not available. Since we don't require this method for testing purposes, I'll + // just stub it + // NB see the slice::hack module in slice.rs for more information #[cfg(test)] - fn to_owned(&self) -> Vec { ::slice::to_vec(self) } + fn to_owned(&self) -> Vec { panic!("not available with cfg(test)") } } //////////////////////////////////////////////////////////////////////////////// @@ -2372,63 +2453,3 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order old } } - -#[cfg(test)] -mod test { - use core::iter::{Iterator, IteratorExt}; - use core::option::Option::{None, Some}; - use string::ToString; - - #[test] - fn test_permutations() { - { - let v: [i32; 0] = []; - let mut it = ::slice::permutations(&v); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 1); - assert_eq!(max_opt.unwrap(), 1); - assert_eq!(it.next(), Some(::slice::to_vec(&v))); - assert_eq!(it.next(), None); - } - { - let v = ["Hello".to_string()]; - let mut it = ::slice::permutations(&v); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 1); - assert_eq!(max_opt.unwrap(), 1); - assert_eq!(it.next(), Some(::slice::to_vec(&v))); - assert_eq!(it.next(), None); - } - { - let v = [1, 2, 3]; - let mut it = ::slice::permutations(&v); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 3*2); - assert_eq!(max_opt.unwrap(), 3*2); - assert_eq!(it.next().unwrap(), [1,2,3]); - assert_eq!(it.next().unwrap(), [1,3,2]); - assert_eq!(it.next().unwrap(), [3,1,2]); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 3); - assert_eq!(max_opt.unwrap(), 3); - assert_eq!(it.next().unwrap(), [3,2,1]); - assert_eq!(it.next().unwrap(), [2,3,1]); - assert_eq!(it.next().unwrap(), [2,1,3]); - assert_eq!(it.next(), None); - } - { - // check that we have N! permutations - let v = ['A', 'B', 'C', 'D', 'E', 'F']; - let mut amt = 0; - let mut it = ::slice::permutations(&v); - let (min_size, max_opt) = it.size_hint(); - for _perm in it.by_ref() { - amt += 1; - } - assert_eq!(amt, it.swaps.swaps_made); - assert_eq!(amt, min_size); - assert_eq!(amt, 2 * 3 * 4 * 5 * 6); - assert_eq!(amt, max_opt.unwrap()); - } - } -} diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index fdc7cf993b118..9d178eb5413c3 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -118,12 +118,14 @@ impl String { String { vec: <[_]>::to_vec(string.as_bytes()) } } - // HACK: `impl [T]` is not available in cfg(test), use `::slice::to_vec` instead of - // `<[T]>::to_vec` + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is required for this + // method definition, is not available. Since we don't require this method for testing + // purposes, I'll just stub it + // NB see the slice::hack module in slice.rs for more information #[inline] #[cfg(test)] - pub fn from_str(string: &str) -> String { - String { vec: ::slice::to_vec(string.as_bytes()) } + pub fn from_str(_: &str) -> String { + panic!("not available with cfg(test)"); } /// Returns the vector as a string buffer, if possible, taking care not to diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 6aaebe08f5c26..3bd57cc362448 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1290,10 +1290,15 @@ impl Clone for Vec { #[cfg(not(test))] fn clone(&self) -> Vec { <[T]>::to_vec(&**self) } - // HACK: `impl [T]` not available in cfg(test), use `::slice::to_vec` instead of `<[T]>::to_vec` + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is required for this + // method definition, is not available. Instead use the `slice::to_vec` function which is only + // available with cfg(test) + // NB see the slice::hack module in slice.rs for more information #[cfg(not(stage0))] #[cfg(test)] - fn clone(&self) -> Vec { ::slice::to_vec(&**self) } + fn clone(&self) -> Vec { + ::slice::to_vec(&**self) + } fn clone_from(&mut self, other: &Vec) { // drop anything in self that will not be overwritten