From 5b75e44fb01f0eda10ce8d8df92b80945d894768 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:04:56 -0700 Subject: core: Inherit the intrinsics module --- src/libstd/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libstd/lib.rs') diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index bf24bf405a0..2c971542960 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -122,8 +122,8 @@ // Make and rand accessible for benchmarking/testcases #[cfg(test)] extern crate rand; -// we wrap some libc stuff extern crate libc; +extern crate core; // Make std testable by not duplicating lang items. See #2912 #[cfg(test)] extern crate realstd = "std"; @@ -133,6 +133,8 @@ extern crate libc; #[cfg(test)] pub use ty = realstd::ty; #[cfg(test)] pub use owned = realstd::owned; +pub use core::intrinsics; + // Run tests with libgreen instead of libnative. // // FIXME: This egregiously hacks around starting the test runner in a different @@ -255,8 +257,6 @@ pub mod reflect; #[unstable] pub mod unstable; #[experimental] -pub mod intrinsics; -#[experimental] pub mod raw; /* For internal use, not exported */ -- cgit 1.4.1-3-g733a5 From dca8a0d6e4d1848ead898b3fa5b1e6c940c85b87 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:13:05 -0700 Subject: core: Inherit the mem module --- src/libcore/lib.rs | 1 + src/libcore/mem.rs | 458 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/lib.rs | 3 +- src/libstd/mem.rs | 460 ----------------------------------------------------- 4 files changed, 460 insertions(+), 462 deletions(-) create mode 100644 src/libcore/mem.rs delete mode 100644 src/libstd/mem.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index b76d3b84254..a0cadd6fc72 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -24,3 +24,4 @@ /* Core modules for ownership management */ pub mod intrinsics; +pub mod mem; diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs new file mode 100644 index 00000000000..860304232d4 --- /dev/null +++ b/src/libcore/mem.rs @@ -0,0 +1,458 @@ +// 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. + +//! Basic functions for dealing with memory +//! +//! This module contains functions for querying the size and alignment of +//! types, initializing and manipulating memory. + +use cast; +use ptr; +use intrinsics; +use intrinsics::{bswap16, bswap32, bswap64}; + +/// Returns the size of a type in bytes. +#[inline] +pub fn size_of() -> uint { + unsafe { intrinsics::size_of::() } +} + +/// Returns the size of the type that `_val` points to in bytes. +#[inline] +pub fn size_of_val(_val: &T) -> uint { + size_of::() +} + +/// Returns the size of a type in bytes, or 1 if the actual size is zero. +/// +/// Useful for building structures containing variable-length arrays. +#[inline] +pub fn nonzero_size_of() -> uint { + match size_of::() { + 0 => 1, + x => x + } +} + +/// Returns the size in bytes of the type of the value that `_val` points to. +#[inline] +pub fn nonzero_size_of_val(_val: &T) -> uint { + nonzero_size_of::() +} + +/// Returns the ABI-required minimum alignment of a type +/// +/// This is the alignment used for struct fields. It may be smaller +/// than the preferred alignment. +#[inline] +pub fn min_align_of() -> uint { + unsafe { intrinsics::min_align_of::() } +} + +/// Returns the ABI-required minimum alignment of the type of the value that +/// `_val` points to +#[inline] +pub fn min_align_of_val(_val: &T) -> uint { + min_align_of::() +} + +/// Returns the preferred alignment of a type +#[inline] +pub fn pref_align_of() -> uint { + unsafe { intrinsics::pref_align_of::() } +} + +/// Returns the preferred alignment of the type of the value that +/// `_val` points to +#[inline] +pub fn pref_align_of_val(_val: &T) -> uint { + pref_align_of::() +} + +/// Create a value initialized to zero. +/// +/// `init` is unsafe because it returns a zeroed-out datum, +/// which is unsafe unless T is Copy. +#[inline] +pub unsafe fn init() -> T { + intrinsics::init() +} + +/// Create an uninitialized value. +#[inline] +pub unsafe fn uninit() -> T { + intrinsics::uninit() +} + +/// Move a value to an uninitialized memory location. +/// +/// Drop glue is not run on the destination. +#[inline] +pub unsafe fn move_val_init(dst: &mut T, src: T) { + intrinsics::move_val_init(dst, src) +} + +/// Convert an u16 to little endian from the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: u16) -> u16 { x } + +/// Convert an u16 to little endian from the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn to_le16(x: u16) -> u16 { unsafe { bswap16(x) } } + +/// Convert an u32 to little endian from the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn to_le32(x: u32) -> u32 { x } + +/// Convert an u32 to little endian from the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn to_le32(x: u32) -> u32 { unsafe { bswap32(x) } } + +/// Convert an u64 to little endian from the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn to_le64(x: u64) -> u64 { x } + +/// Convert an u64 to little endian from the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn to_le64(x: u64) -> u64 { unsafe { bswap64(x) } } + + +/// Convert an u16 to big endian from the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn to_be16(x: u16) -> u16 { unsafe { bswap16(x) } } + +/// Convert an u16 to big endian from the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn to_be16(x: u16) -> u16 { x } + +/// Convert an u32 to big endian from the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn to_be32(x: u32) -> u32 { unsafe { bswap32(x) } } + +/// Convert an u32 to big endian from the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn to_be32(x: u32) -> u32 { x } + +/// Convert an u64 to big endian from the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn to_be64(x: u64) -> u64 { unsafe { bswap64(x) } } + +/// Convert an u64 to big endian from the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn to_be64(x: u64) -> u64 { x } + + +/// Convert an u16 from little endian to the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn from_le16(x: u16) -> u16 { x } + +/// Convert an u16 from little endian to the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn from_le16(x: u16) -> u16 { unsafe { bswap16(x) } } + +/// Convert an u32 from little endian to the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn from_le32(x: u32) -> u32 { x } + +/// Convert an u32 from little endian to the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn from_le32(x: u32) -> u32 { unsafe { bswap32(x) } } + +/// Convert an u64 from little endian to the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn from_le64(x: u64) -> u64 { x } + +/// Convert an u64 from little endian to the target's endianness. +/// +/// On little endian, this is a no-op. On big endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn from_le64(x: u64) -> u64 { unsafe { bswap64(x) } } + + +/// Convert an u16 from big endian to the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn from_be16(x: u16) -> u16 { unsafe { bswap16(x) } } + +/// Convert an u16 from big endian to the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn from_be16(x: u16) -> u16 { x } + +/// Convert an u32 from big endian to the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn from_be32(x: u32) -> u32 { unsafe { bswap32(x) } } + +/// Convert an u32 from big endian to the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn from_be32(x: u32) -> u32 { x } + +/// Convert an u64 from big endian to the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "little")] #[inline] pub fn from_be64(x: u64) -> u64 { unsafe { bswap64(x) } } + +/// Convert an u64 from big endian to the target's endianness. +/// +/// On big endian, this is a no-op. On little endian, the bytes are swapped. +#[cfg(target_endian = "big")] #[inline] pub fn from_be64(x: u64) -> u64 { x } + +/** + * Swap the values at two mutable locations of the same type, without + * deinitialising or copying either one. + */ +#[inline] +pub fn swap(x: &mut T, y: &mut T) { + unsafe { + // Give ourselves some scratch space to work with + let mut t: T = uninit(); + + // Perform the swap, `&mut` pointers never alias + ptr::copy_nonoverlapping_memory(&mut t, &*x, 1); + ptr::copy_nonoverlapping_memory(x, &*y, 1); + ptr::copy_nonoverlapping_memory(y, &t, 1); + + // y and t now point to the same thing, but we need to completely forget `t` + // because it's no longer relevant. + cast::forget(t); + } +} + +/** + * Replace the value at a mutable location with a new one, returning the old + * value, without deinitialising or copying either one. + * + * This is primarily used for transferring and swapping ownership of a value + * in a mutable location. For example, this function allows consumption of + * one field of a struct by replacing it with another value. The normal approach + * doesn't always work: + * + * ```rust,ignore + * struct Buffer { buf: Vec } + * + * impl Buffer { + * fn get_and_reset(&mut self) -> Vec { + * // error: cannot move out of dereference of `&mut`-pointer + * let buf = self.buf; + * self.buf = Vec::new(); + * buf + * } + * } + * ``` + * + * Note that `T` does not necessarily implement `Clone`, so it can't even + * clone and reset `self.buf`. But `replace` can be used to disassociate + * the original value of `self.buf` from `self`, allowing it to be returned: + * + * ```rust + * # struct Buffer { buf: Vec } + * impl Buffer { + * fn get_and_reset(&mut self) -> Vec { + * use std::mem::replace; + * replace(&mut self.buf, Vec::new()) + * } + * } + * ``` + */ +#[inline] +pub fn replace(dest: &mut T, mut src: T) -> T { + swap(dest, &mut src); + src +} + +/// Disposes of a value. +#[inline] +pub fn drop(_x: T) { } + +#[cfg(test)] +mod tests { + use mem::*; + use option::{Some,None}; + use str::StrSlice; + + #[test] + fn size_of_basic() { + assert_eq!(size_of::(), 1u); + assert_eq!(size_of::(), 2u); + assert_eq!(size_of::(), 4u); + assert_eq!(size_of::(), 8u); + } + + #[test] + #[cfg(target_arch = "x86")] + #[cfg(target_arch = "arm")] + #[cfg(target_arch = "mips")] + fn size_of_32() { + assert_eq!(size_of::(), 4u); + assert_eq!(size_of::<*uint>(), 4u); + } + + #[test] + #[cfg(target_arch = "x86_64")] + fn size_of_64() { + assert_eq!(size_of::(), 8u); + assert_eq!(size_of::<*uint>(), 8u); + } + + #[test] + fn size_of_val_basic() { + assert_eq!(size_of_val(&1u8), 1); + assert_eq!(size_of_val(&1u16), 2); + assert_eq!(size_of_val(&1u32), 4); + assert_eq!(size_of_val(&1u64), 8); + } + + #[test] + fn nonzero_size_of_basic() { + type Z = [i8, ..0]; + assert_eq!(size_of::(), 0u); + assert_eq!(nonzero_size_of::(), 1u); + assert_eq!(nonzero_size_of::(), size_of::()); + } + + #[test] + fn nonzero_size_of_val_basic() { + let z = [0u8, ..0]; + assert_eq!(size_of_val(&z), 0u); + assert_eq!(nonzero_size_of_val(&z), 1u); + assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u)); + } + + #[test] + fn align_of_basic() { + assert_eq!(pref_align_of::(), 1u); + assert_eq!(pref_align_of::(), 2u); + assert_eq!(pref_align_of::(), 4u); + } + + #[test] + #[cfg(target_arch = "x86")] + #[cfg(target_arch = "arm")] + #[cfg(target_arch = "mips")] + fn align_of_32() { + assert_eq!(pref_align_of::(), 4u); + assert_eq!(pref_align_of::<*uint>(), 4u); + } + + #[test] + #[cfg(target_arch = "x86_64")] + fn align_of_64() { + assert_eq!(pref_align_of::(), 8u); + assert_eq!(pref_align_of::<*uint>(), 8u); + } + + #[test] + fn align_of_val_basic() { + assert_eq!(pref_align_of_val(&1u8), 1u); + assert_eq!(pref_align_of_val(&1u16), 2u); + assert_eq!(pref_align_of_val(&1u32), 4u); + } + + #[test] + fn test_swap() { + let mut x = 31337; + let mut y = 42; + swap(&mut x, &mut y); + assert_eq!(x, 42); + assert_eq!(y, 31337); + } + + #[test] + fn test_replace() { + let mut x = Some("test".to_owned()); + let y = replace(&mut x, None); + assert!(x.is_none()); + assert!(y.is_some()); + } +} + +// FIXME #13642 (these benchmarks should be in another place) +/// Completely miscellaneous language-construct benchmarks. +#[cfg(test)] +mod bench { + extern crate test; + use self::test::Bencher; + use option::{Some,None}; + + // Static/dynamic method dispatch + + struct Struct { + field: int + } + + trait Trait { + fn method(&self) -> int; + } + + impl Trait for Struct { + fn method(&self) -> int { + self.field + } + } + + #[bench] + fn trait_vtable_method_call(b: &mut Bencher) { + let s = Struct { field: 10 }; + let t = &s as &Trait; + b.iter(|| { + t.method() + }); + } + + #[bench] + fn trait_static_method_call(b: &mut Bencher) { + let s = Struct { field: 10 }; + b.iter(|| { + s.method() + }); + } + + // Overhead of various match forms + + #[bench] + fn match_option_some(b: &mut Bencher) { + let x = Some(10); + b.iter(|| { + match x { + Some(y) => y, + None => 11 + } + }); + } + + #[bench] + fn match_vec_pattern(b: &mut Bencher) { + let x = [1,2,3,4,5,6]; + b.iter(|| { + match x { + [1,2,3,..] => 10, + _ => 11 + } + }); + } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 2c971542960..9ef657f6e4a 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -134,6 +134,7 @@ extern crate core; #[cfg(test)] pub use owned = realstd::owned; pub use core::intrinsics; +pub use core::mem; // Run tests with libgreen instead of libnative. // @@ -243,8 +244,6 @@ pub mod path; pub mod cast; pub mod fmt; pub mod cleanup; -pub mod mem; - /* Unsupported interfaces */ diff --git a/src/libstd/mem.rs b/src/libstd/mem.rs deleted file mode 100644 index d216d91b901..00000000000 --- a/src/libstd/mem.rs +++ /dev/null @@ -1,460 +0,0 @@ -// 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. - -//! Basic functions for dealing with memory -//! -//! This module contains functions for querying the size and alignment of -//! types, initializing and manipulating memory. - -#![allow(missing_doc)] // FIXME - -use cast; -use ptr; -use intrinsics; -use intrinsics::{bswap16, bswap32, bswap64}; - -/// Returns the size of a type in bytes. -#[inline] -pub fn size_of() -> uint { - unsafe { intrinsics::size_of::() } -} - -/// Returns the size of the type that `_val` points to in bytes. -#[inline] -pub fn size_of_val(_val: &T) -> uint { - size_of::() -} - -/// Returns the size of a type in bytes, or 1 if the actual size is zero. -/// -/// Useful for building structures containing variable-length arrays. -#[inline] -pub fn nonzero_size_of() -> uint { - match size_of::() { - 0 => 1, - x => x - } -} - -/// Returns the size in bytes of the type of the value that `_val` points to. -#[inline] -pub fn nonzero_size_of_val(_val: &T) -> uint { - nonzero_size_of::() -} - -/// Returns the ABI-required minimum alignment of a type -/// -/// This is the alignment used for struct fields. It may be smaller -/// than the preferred alignment. -#[inline] -pub fn min_align_of() -> uint { - unsafe { intrinsics::min_align_of::() } -} - -/// Returns the ABI-required minimum alignment of the type of the value that -/// `_val` points to -#[inline] -pub fn min_align_of_val(_val: &T) -> uint { - min_align_of::() -} - -/// Returns the preferred alignment of a type -#[inline] -pub fn pref_align_of() -> uint { - unsafe { intrinsics::pref_align_of::() } -} - -/// Returns the preferred alignment of the type of the value that -/// `_val` points to -#[inline] -pub fn pref_align_of_val(_val: &T) -> uint { - pref_align_of::() -} - -/// Create a value initialized to zero. -/// -/// `init` is unsafe because it returns a zeroed-out datum, -/// which is unsafe unless T is Copy. -#[inline] -pub unsafe fn init() -> T { - intrinsics::init() -} - -/// Create an uninitialized value. -#[inline] -pub unsafe fn uninit() -> T { - intrinsics::uninit() -} - -/// Move a value to an uninitialized memory location. -/// -/// Drop glue is not run on the destination. -#[inline] -pub unsafe fn move_val_init(dst: &mut T, src: T) { - intrinsics::move_val_init(dst, src) -} - -/// Convert an u16 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: u16) -> u16 { x } - -/// Convert an u16 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn to_le16(x: u16) -> u16 { unsafe { bswap16(x) } } - -/// Convert an u32 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn to_le32(x: u32) -> u32 { x } - -/// Convert an u32 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn to_le32(x: u32) -> u32 { unsafe { bswap32(x) } } - -/// Convert an u64 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn to_le64(x: u64) -> u64 { x } - -/// Convert an u64 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn to_le64(x: u64) -> u64 { unsafe { bswap64(x) } } - - -/// Convert an u16 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn to_be16(x: u16) -> u16 { unsafe { bswap16(x) } } - -/// Convert an u16 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn to_be16(x: u16) -> u16 { x } - -/// Convert an u32 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn to_be32(x: u32) -> u32 { unsafe { bswap32(x) } } - -/// Convert an u32 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn to_be32(x: u32) -> u32 { x } - -/// Convert an u64 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn to_be64(x: u64) -> u64 { unsafe { bswap64(x) } } - -/// Convert an u64 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn to_be64(x: u64) -> u64 { x } - - -/// Convert an u16 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn from_le16(x: u16) -> u16 { x } - -/// Convert an u16 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn from_le16(x: u16) -> u16 { unsafe { bswap16(x) } } - -/// Convert an u32 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn from_le32(x: u32) -> u32 { x } - -/// Convert an u32 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn from_le32(x: u32) -> u32 { unsafe { bswap32(x) } } - -/// Convert an u64 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn from_le64(x: u64) -> u64 { x } - -/// Convert an u64 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn from_le64(x: u64) -> u64 { unsafe { bswap64(x) } } - - -/// Convert an u16 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn from_be16(x: u16) -> u16 { unsafe { bswap16(x) } } - -/// Convert an u16 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn from_be16(x: u16) -> u16 { x } - -/// Convert an u32 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn from_be32(x: u32) -> u32 { unsafe { bswap32(x) } } - -/// Convert an u32 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn from_be32(x: u32) -> u32 { x } - -/// Convert an u64 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn from_be64(x: u64) -> u64 { unsafe { bswap64(x) } } - -/// Convert an u64 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] pub fn from_be64(x: u64) -> u64 { x } - -/** - * Swap the values at two mutable locations of the same type, without - * deinitialising or copying either one. - */ -#[inline] -pub fn swap(x: &mut T, y: &mut T) { - unsafe { - // Give ourselves some scratch space to work with - let mut t: T = uninit(); - - // Perform the swap, `&mut` pointers never alias - ptr::copy_nonoverlapping_memory(&mut t, &*x, 1); - ptr::copy_nonoverlapping_memory(x, &*y, 1); - ptr::copy_nonoverlapping_memory(y, &t, 1); - - // y and t now point to the same thing, but we need to completely forget `t` - // because it's no longer relevant. - cast::forget(t); - } -} - -/** - * Replace the value at a mutable location with a new one, returning the old - * value, without deinitialising or copying either one. - * - * This is primarily used for transferring and swapping ownership of a value - * in a mutable location. For example, this function allows consumption of - * one field of a struct by replacing it with another value. The normal approach - * doesn't always work: - * - * ```rust,ignore - * struct Buffer { buf: Vec } - * - * impl Buffer { - * fn get_and_reset(&mut self) -> Vec { - * // error: cannot move out of dereference of `&mut`-pointer - * let buf = self.buf; - * self.buf = Vec::new(); - * buf - * } - * } - * ``` - * - * Note that `T` does not necessarily implement `Clone`, so it can't even - * clone and reset `self.buf`. But `replace` can be used to disassociate - * the original value of `self.buf` from `self`, allowing it to be returned: - * - * ```rust - * # struct Buffer { buf: Vec } - * impl Buffer { - * fn get_and_reset(&mut self) -> Vec { - * use std::mem::replace; - * replace(&mut self.buf, Vec::new()) - * } - * } - * ``` - */ -#[inline] -pub fn replace(dest: &mut T, mut src: T) -> T { - swap(dest, &mut src); - src -} - -/// Disposes of a value. -#[inline] -pub fn drop(_x: T) { } - -#[cfg(test)] -mod tests { - use mem::*; - use option::{Some,None}; - use str::StrSlice; - - #[test] - fn size_of_basic() { - assert_eq!(size_of::(), 1u); - assert_eq!(size_of::(), 2u); - assert_eq!(size_of::(), 4u); - assert_eq!(size_of::(), 8u); - } - - #[test] - #[cfg(target_arch = "x86")] - #[cfg(target_arch = "arm")] - #[cfg(target_arch = "mips")] - fn size_of_32() { - assert_eq!(size_of::(), 4u); - assert_eq!(size_of::<*uint>(), 4u); - } - - #[test] - #[cfg(target_arch = "x86_64")] - fn size_of_64() { - assert_eq!(size_of::(), 8u); - assert_eq!(size_of::<*uint>(), 8u); - } - - #[test] - fn size_of_val_basic() { - assert_eq!(size_of_val(&1u8), 1); - assert_eq!(size_of_val(&1u16), 2); - assert_eq!(size_of_val(&1u32), 4); - assert_eq!(size_of_val(&1u64), 8); - } - - #[test] - fn nonzero_size_of_basic() { - type Z = [i8, ..0]; - assert_eq!(size_of::(), 0u); - assert_eq!(nonzero_size_of::(), 1u); - assert_eq!(nonzero_size_of::(), size_of::()); - } - - #[test] - fn nonzero_size_of_val_basic() { - let z = [0u8, ..0]; - assert_eq!(size_of_val(&z), 0u); - assert_eq!(nonzero_size_of_val(&z), 1u); - assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u)); - } - - #[test] - fn align_of_basic() { - assert_eq!(pref_align_of::(), 1u); - assert_eq!(pref_align_of::(), 2u); - assert_eq!(pref_align_of::(), 4u); - } - - #[test] - #[cfg(target_arch = "x86")] - #[cfg(target_arch = "arm")] - #[cfg(target_arch = "mips")] - fn align_of_32() { - assert_eq!(pref_align_of::(), 4u); - assert_eq!(pref_align_of::<*uint>(), 4u); - } - - #[test] - #[cfg(target_arch = "x86_64")] - fn align_of_64() { - assert_eq!(pref_align_of::(), 8u); - assert_eq!(pref_align_of::<*uint>(), 8u); - } - - #[test] - fn align_of_val_basic() { - assert_eq!(pref_align_of_val(&1u8), 1u); - assert_eq!(pref_align_of_val(&1u16), 2u); - assert_eq!(pref_align_of_val(&1u32), 4u); - } - - #[test] - fn test_swap() { - let mut x = 31337; - let mut y = 42; - swap(&mut x, &mut y); - assert_eq!(x, 42); - assert_eq!(y, 31337); - } - - #[test] - fn test_replace() { - let mut x = Some("test".to_owned()); - let y = replace(&mut x, None); - assert!(x.is_none()); - assert!(y.is_some()); - } -} - -// FIXME #13642 (these benchmarks should be in another place) -/// Completely miscellaneous language-construct benchmarks. -#[cfg(test)] -mod bench { - extern crate test; - use self::test::Bencher; - use option::{Some,None}; - - // Static/dynamic method dispatch - - struct Struct { - field: int - } - - trait Trait { - fn method(&self) -> int; - } - - impl Trait for Struct { - fn method(&self) -> int { - self.field - } - } - - #[bench] - fn trait_vtable_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - let t = &s as &Trait; - b.iter(|| { - t.method() - }); - } - - #[bench] - fn trait_static_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - b.iter(|| { - s.method() - }); - } - - // Overhead of various match forms - - #[bench] - fn match_option_some(b: &mut Bencher) { - let x = Some(10); - b.iter(|| { - match x { - Some(y) => y, - None => 11 - } - }); - } - - #[bench] - fn match_vec_pattern(b: &mut Bencher) { - let x = [1,2,3,4,5,6]; - b.iter(|| { - match x { - [1,2,3,..] => 10, - _ => 11 - } - }); - } -} -- cgit 1.4.1-3-g733a5 From 645b1575641209b63d55ff711f83193465f8e082 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:17:50 -0700 Subject: core: Inherit the ptr module --- src/libcore/lib.rs | 1 + src/libcore/ptr.rs | 736 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/lib.rs | 3 +- src/libstd/ptr.rs | 772 ----------------------------------------------------- 4 files changed, 739 insertions(+), 773 deletions(-) create mode 100644 src/libcore/ptr.rs delete mode 100644 src/libstd/ptr.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a0cadd6fc72..bbbadad6e36 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -25,3 +25,4 @@ pub mod intrinsics; pub mod mem; +pub mod ptr; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs new file mode 100644 index 00000000000..9ac9e62b50d --- /dev/null +++ b/src/libcore/ptr.rs @@ -0,0 +1,736 @@ +// Copyright 2012-2013 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. + +//! Conveniences for working with unsafe pointers, the `*T`, and `*mut T` types. +//! +//! Working with unsafe pointers in Rust is fairly uncommon, +//! and often limited to some narrow use cases: holding +//! an unsafe pointer when safe pointers are unsuitable; +//! checking for null; and converting back to safe pointers. +//! As a result, there is not yet an abundance of library code +//! for working with unsafe pointers, and in particular, +//! since pointer math is fairly uncommon in Rust, it is not +//! all that convenient. +//! +//! Use the [`null` function](fn.null.html) to create null pointers, +//! the [`is_null`](trait.RawPtr.html#tymethod.is_null) +//! and [`is_not_null`](trait.RawPtr.html#method.is_not_null) +//! methods of the [`RawPtr` trait](trait.RawPtr.html) to check for null. +//! The `RawPtr` trait is imported by the prelude, so `is_null` etc. +//! work everywhere. +//! +//! # Common ways to create unsafe pointers +//! +//! ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`). +//! +//! ``` +//! let my_num: int = 10; +//! let my_num_ptr: *int = &my_num; +//! let mut my_speed: int = 88; +//! let my_speed_ptr: *mut int = &mut my_speed; +//! ``` +//! +//! This does not take ownership of the original allocation +//! and requires no resource management later, +//! but you must not use the pointer after its lifetime. +//! +//! ## 2. Transmute an owned box (`Box`). +//! +//! The `transmute` function takes, by value, whatever it's given +//! and returns it as whatever type is requested, as long as the +//! types are the same size. Because `Box` and `*T` have the same +//! representation they can be trivially, +//! though unsafely, transformed from one type to the other. +//! +//! ``` +//! use std::cast; +//! +//! unsafe { +//! let my_num: Box = box 10; +//! let my_num: *int = cast::transmute(my_num); +//! let my_speed: Box = box 88; +//! let my_speed: *mut int = cast::transmute(my_speed); +//! +//! // By taking ownership of the original `Box` though +//! // we are obligated to transmute it back later to be destroyed. +//! drop(cast::transmute::<_, Box>(my_speed)); +//! drop(cast::transmute::<_, Box>(my_num)); +//! } +//! ``` +//! +//! Note that here the call to `drop` is for clarity - it indicates +//! that we are done with the given value and it should be destroyed. +//! +//! ## 3. Get it from C. +//! +//! ``` +//! extern crate libc; +//! +//! use std::mem; +//! +//! fn main() { +//! unsafe { +//! let my_num: *mut int = libc::malloc(mem::size_of::() as libc::size_t) as *mut int; +//! if my_num.is_null() { +//! fail!("failed to allocate memory"); +//! } +//! libc::free(my_num as *mut libc::c_void); +//! } +//! } +//! ``` +//! +//! Usually you wouldn't literally use `malloc` and `free` from Rust, +//! but C APIs hand out a lot of pointers generally, so are a common source +//! of unsafe pointers in Rust. + +use cast; +use clone::Clone; +use intrinsics; +use iter::{range, Iterator}; +use mem; +use option::{Some, None, Option}; + +#[cfg(not(test))] use cmp::{Eq, TotalEq, Ord, Equiv}; + +/// Return the offset of the first null pointer in `buf`. +#[inline] +pub unsafe fn buf_len(buf: **T) -> uint { + position(buf, |i| *i == null()) +} + +impl Clone for *T { + #[inline] + fn clone(&self) -> *T { + *self + } +} + +impl Clone for *mut T { + #[inline] + fn clone(&self) -> *mut T { + *self + } +} + +/// Return the first offset `i` such that `f(buf[i]) == true`. +#[inline] +pub unsafe fn position(buf: *T, f: |&T| -> bool) -> uint { + let mut i = 0; + loop { + if f(&(*buf.offset(i as int))) { return i; } + else { i += 1; } + } +} + +/// Create a null pointer. +/// +/// # Example +/// +/// ``` +/// use std::ptr; +/// +/// let p: *int = ptr::null(); +/// assert!(p.is_null()); +/// ``` +#[inline] +pub fn null() -> *T { 0 as *T } + +/// Create an unsafe mutable null pointer. +/// +/// # Example +/// +/// ``` +/// use std::ptr; +/// +/// let p: *mut int = ptr::mut_null(); +/// assert!(p.is_null()); +/// ``` +#[inline] +pub fn mut_null() -> *mut T { 0 as *mut T } + +/// Copies data from one location to another. +/// +/// Copies `count` elements (not bytes) from `src` to `dst`. The source +/// and destination may overlap. +/// +/// `copy_memory` is semantically equivalent to C's `memmove`. +/// +/// # Example +/// +/// Efficiently create a Rust vector from an unsafe buffer: +/// +/// ``` +/// use std::ptr; +/// +/// unsafe fn from_buf_raw(ptr: *T, elts: uint) -> Vec { +/// let mut dst = Vec::with_capacity(elts); +/// dst.set_len(elts); +/// ptr::copy_memory(dst.as_mut_ptr(), ptr, elts); +/// dst +/// } +/// ``` +/// +#[inline] +pub unsafe fn copy_memory(dst: *mut T, src: *T, count: uint) { + intrinsics::copy_memory(dst, src, count) +} + +/// Copies data from one location to another. +/// +/// Copies `count` elements (not bytes) from `src` to `dst`. The source +/// and destination may *not* overlap. +/// +/// `copy_nonoverlapping_memory` is semantically equivalent to C's `memcpy`. +/// +/// # Example +/// +/// A safe swap function: +/// +/// ``` +/// use std::cast; +/// use std::mem; +/// use std::ptr; +/// +/// fn swap(x: &mut T, y: &mut T) { +/// unsafe { +/// // Give ourselves some scratch space to work with +/// let mut t: T = mem::uninit(); +/// +/// // Perform the swap, `&mut` pointers never alias +/// ptr::copy_nonoverlapping_memory(&mut t, &*x, 1); +/// ptr::copy_nonoverlapping_memory(x, &*y, 1); +/// ptr::copy_nonoverlapping_memory(y, &t, 1); +/// +/// // y and t now point to the same thing, but we need to completely forget `tmp` +/// // because it's no longer relevant. +/// cast::forget(t); +/// } +/// } +/// ``` +/// +/// # Safety Note +/// +/// If the source and destination overlap then the behavior of this +/// function is undefined. +#[inline] +pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, + src: *T, + count: uint) { + intrinsics::copy_nonoverlapping_memory(dst, src, count) +} + +/// Invokes memset on the specified pointer, setting `count * size_of::()` +/// bytes of memory starting at `dst` to `c`. +#[inline] +pub unsafe fn set_memory(dst: *mut T, c: u8, count: uint) { + intrinsics::set_memory(dst, c, count) +} + +/// Zeroes out `count * size_of::` bytes of memory at `dst` +#[inline] +pub unsafe fn zero_memory(dst: *mut T, count: uint) { + set_memory(dst, 0, count); +} + +/// Swap the values at two mutable locations of the same type, without +/// deinitialising either. They may overlap. +#[inline] +pub unsafe fn swap(x: *mut T, y: *mut T) { + // Give ourselves some scratch space to work with + let mut tmp: T = mem::uninit(); + let t: *mut T = &mut tmp; + + // Perform the swap + copy_nonoverlapping_memory(t, &*x, 1); + copy_memory(x, &*y, 1); // `x` and `y` may overlap + copy_nonoverlapping_memory(y, &*t, 1); + + // y and t now point to the same thing, but we need to completely forget `tmp` + // because it's no longer relevant. + cast::forget(tmp); +} + +/// Replace the value at a mutable location with a new one, returning the old +/// value, without deinitialising either. +#[inline] +pub unsafe fn replace(dest: *mut T, mut src: T) -> T { + mem::swap(cast::transmute(dest), &mut src); // cannot overlap + src +} + +/// Reads the value from `*src` and returns it. +#[inline(always)] +pub unsafe fn read(src: *T) -> T { + let mut tmp: T = mem::uninit(); + copy_nonoverlapping_memory(&mut tmp, src, 1); + tmp +} + +/// Reads the value from `*src` and nulls it out. +/// This currently prevents destructors from executing. +#[inline(always)] +pub unsafe fn read_and_zero(dest: *mut T) -> T { + // Copy the data out from `dest`: + let tmp = read(&*dest); + + // Now zero out `dest`: + zero_memory(dest, 1); + + tmp +} + +/// Given a **T (pointer to an array of pointers), +/// iterate through each *T, up to the provided `len`, +/// passing to the provided callback function +pub unsafe fn array_each_with_len(arr: **T, len: uint, cb: |*T|) { + if arr.is_null() { + fail!("ptr::array_each_with_len failure: arr input is null pointer"); + } + //let start_ptr = *arr; + for e in range(0, len) { + let n = arr.offset(e as int); + cb(*n); + } +} + +/// Given a null-pointer-terminated **T (pointer to +/// an array of pointers), iterate through each *T, +/// passing to the provided callback function +/// +/// # Safety Note +/// +/// This will only work with a null-terminated +/// pointer array. +pub unsafe fn array_each(arr: **T, cb: |*T|) { + if arr.is_null() { + fail!("ptr::array_each_with_len failure: arr input is null pointer"); + } + let len = buf_len(arr); + array_each_with_len(arr, len, cb); +} + +/// Extension methods for raw pointers. +pub trait RawPtr { + /// Returns the null pointer. + fn null() -> Self; + /// Returns true if the pointer is equal to the null pointer. + fn is_null(&self) -> bool; + /// Returns true if the pointer is not equal to the null pointer. + fn is_not_null(&self) -> bool { !self.is_null() } + /// Returns the value of this pointer (ie, the address it points to) + fn to_uint(&self) -> uint; + /// Returns `None` if the pointer is null, or else returns the value wrapped + /// in `Some`. + /// + /// # Safety Notes + /// + /// While this method is 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. + unsafe fn to_option(&self) -> Option<&T>; + /// Calculates the offset from a pointer. The offset *must* be in-bounds of + /// the object, or one-byte-past-the-end. `count` is in units of T; e.g. a + /// `count` of 3 represents a pointer offset of `3 * sizeof::()` bytes. + unsafe fn offset(self, count: int) -> Self; +} + +impl RawPtr for *T { + #[inline] + fn null() -> *T { null() } + + #[inline] + fn is_null(&self) -> bool { *self == RawPtr::null() } + + #[inline] + fn to_uint(&self) -> uint { *self as uint } + + #[inline] + unsafe fn offset(self, count: int) -> *T { intrinsics::offset(self, count) } + + #[inline] + unsafe fn to_option(&self) -> Option<&T> { + if self.is_null() { + None + } else { + Some(cast::transmute(*self)) + } + } +} + +impl RawPtr for *mut T { + #[inline] + fn null() -> *mut T { mut_null() } + + #[inline] + fn is_null(&self) -> bool { *self == RawPtr::null() } + + #[inline] + fn to_uint(&self) -> uint { *self as uint } + + #[inline] + unsafe fn offset(self, count: int) -> *mut T { + intrinsics::offset(self as *T, count) as *mut T + } + + #[inline] + unsafe fn to_option(&self) -> Option<&T> { + if self.is_null() { + None + } else { + Some(cast::transmute(*self)) + } + } +} + +// Equality for pointers +#[cfg(not(test))] +impl Eq for *T { + #[inline] + fn eq(&self, other: &*T) -> bool { + *self == *other + } + #[inline] + fn ne(&self, other: &*T) -> bool { !self.eq(other) } +} + +#[cfg(not(test))] +impl TotalEq for *T {} + +#[cfg(not(test))] +impl Eq for *mut T { + #[inline] + fn eq(&self, other: &*mut T) -> bool { + *self == *other + } + #[inline] + fn ne(&self, other: &*mut T) -> bool { !self.eq(other) } +} + +#[cfg(not(test))] +impl TotalEq for *mut T {} + +// Equivalence for pointers +#[cfg(not(test))] +impl Equiv<*mut T> for *T { + fn equiv(&self, other: &*mut T) -> bool { + self.to_uint() == other.to_uint() + } +} + +#[cfg(not(test))] +impl Equiv<*T> for *mut T { + fn equiv(&self, other: &*T) -> bool { + self.to_uint() == other.to_uint() + } +} + +// Equality for extern "C" fn pointers +#[cfg(not(test))] +mod externfnpointers { + use cast; + use cmp::Eq; + + impl<_R> Eq for extern "C" fn() -> _R { + #[inline] + fn eq(&self, other: &extern "C" fn() -> _R) -> bool { + let self_: *() = unsafe { cast::transmute(*self) }; + let other_: *() = unsafe { cast::transmute(*other) }; + self_ == other_ + } + } + macro_rules! fnptreq( + ($($p:ident),*) => { + impl<_R,$($p),*> Eq for extern "C" fn($($p),*) -> _R { + #[inline] + fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool { + let self_: *() = unsafe { cast::transmute(*self) }; + let other_: *() = unsafe { cast::transmute(*other) }; + self_ == other_ + } + } + } + ) + fnptreq!(A) + fnptreq!(A,B) + fnptreq!(A,B,C) + fnptreq!(A,B,C,D) + fnptreq!(A,B,C,D,E) +} + +// Comparison for pointers +#[cfg(not(test))] +impl Ord for *T { + #[inline] + fn lt(&self, other: &*T) -> bool { *self < *other } +} + +#[cfg(not(test))] +impl Ord for *mut T { + #[inline] + fn lt(&self, other: &*mut T) -> bool { *self < *other } +} + +#[cfg(test)] +pub mod ptr_tests { + use super::*; + use prelude::*; + + use c_str::ToCStr; + use cast; + use libc; + use str; + use slice::{ImmutableVector, MutableVector}; + + #[test] + fn test() { + unsafe { + struct Pair { + fst: int, + snd: int + }; + let mut p = Pair {fst: 10, snd: 20}; + let pptr: *mut Pair = &mut p; + let iptr: *mut int = cast::transmute(pptr); + assert_eq!(*iptr, 10); + *iptr = 30; + assert_eq!(*iptr, 30); + assert_eq!(p.fst, 30); + + *pptr = Pair {fst: 50, snd: 60}; + assert_eq!(*iptr, 50); + assert_eq!(p.fst, 50); + assert_eq!(p.snd, 60); + + let v0 = box [32000u16, 32001u16, 32002u16]; + let mut v1 = box [0u16, 0u16, 0u16]; + + copy_memory(v1.as_mut_ptr().offset(1), + v0.as_ptr().offset(1), 1); + assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16)); + copy_memory(v1.as_mut_ptr(), + v0.as_ptr().offset(2), 1); + assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && + v1[2] == 0u16)); + copy_memory(v1.as_mut_ptr().offset(2), + v0.as_ptr(), 1u); + assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && + v1[2] == 32000u16)); + } + } + + #[test] + fn test_position() { + use libc::c_char; + + "hello".with_c_str(|p| { + unsafe { + assert!(2u == position(p, |c| *c == 'l' as c_char)); + assert!(4u == position(p, |c| *c == 'o' as c_char)); + assert!(5u == position(p, |c| *c == 0 as c_char)); + } + }) + } + + #[test] + fn test_buf_len() { + "hello".with_c_str(|p0| { + "there".with_c_str(|p1| { + "thing".with_c_str(|p2| { + let v = box [p0, p1, p2, null()]; + unsafe { + assert_eq!(buf_len(v.as_ptr()), 3u); + } + }) + }) + }) + } + + #[test] + fn test_is_null() { + let p: *int = null(); + assert!(p.is_null()); + assert!(!p.is_not_null()); + + let q = unsafe { p.offset(1) }; + assert!(!q.is_null()); + assert!(q.is_not_null()); + + let mp: *mut int = mut_null(); + assert!(mp.is_null()); + assert!(!mp.is_not_null()); + + let mq = unsafe { mp.offset(1) }; + assert!(!mq.is_null()); + assert!(mq.is_not_null()); + } + + #[test] + fn test_to_option() { + unsafe { + let p: *int = null(); + assert_eq!(p.to_option(), None); + + let q: *int = &2; + assert_eq!(q.to_option().unwrap(), &2); + + let p: *mut int = mut_null(); + assert_eq!(p.to_option(), None); + + let q: *mut int = &mut 2; + assert_eq!(q.to_option().unwrap(), &2); + } + } + + #[test] + fn test_ptr_addition() { + unsafe { + let xs = box [5, ..16]; + let mut ptr = xs.as_ptr(); + let end = ptr.offset(16); + + while ptr < end { + assert_eq!(*ptr, 5); + ptr = ptr.offset(1); + } + + let mut xs_mut = xs.clone(); + let mut m_ptr = xs_mut.as_mut_ptr(); + let m_end = m_ptr.offset(16); + + while m_ptr < m_end { + *m_ptr += 5; + m_ptr = m_ptr.offset(1); + } + + assert_eq!(xs_mut, box [10, ..16]); + } + } + + #[test] + fn test_ptr_subtraction() { + unsafe { + let xs = box [0,1,2,3,4,5,6,7,8,9]; + let mut idx = 9i8; + let ptr = xs.as_ptr(); + + while idx >= 0i8 { + assert_eq!(*(ptr.offset(idx as int)), idx as int); + idx = idx - 1i8; + } + + let mut xs_mut = xs.clone(); + let m_start = xs_mut.as_mut_ptr(); + let mut m_ptr = m_start.offset(9); + + while m_ptr >= m_start { + *m_ptr += *m_ptr; + m_ptr = m_ptr.offset(-1); + } + + assert_eq!(xs_mut, box [0,2,4,6,8,10,12,14,16,18]); + } + } + + #[test] + fn test_ptr_array_each_with_len() { + unsafe { + let one = "oneOne".to_c_str(); + let two = "twoTwo".to_c_str(); + let three = "threeThree".to_c_str(); + let arr = box [ + one.with_ref(|buf| buf), + two.with_ref(|buf| buf), + three.with_ref(|buf| buf), + ]; + let expected_arr = [ + one, two, three + ]; + + let mut ctr = 0; + let mut iteration_count = 0; + array_each_with_len(arr.as_ptr(), arr.len(), |e| { + let actual = str::raw::from_c_str(e); + let expected = expected_arr[ctr].with_ref(|buf| { + str::raw::from_c_str(buf) + }); + debug!( + "test_ptr_array_each_with_len e: {}, a: {}", + expected, actual); + assert_eq!(actual, expected); + ctr += 1; + iteration_count += 1; + }); + assert_eq!(iteration_count, 3u); + } + } + + #[test] + fn test_ptr_array_each() { + unsafe { + let one = "oneOne".to_c_str(); + let two = "twoTwo".to_c_str(); + let three = "threeThree".to_c_str(); + let arr = box [ + one.with_ref(|buf| buf), + two.with_ref(|buf| buf), + three.with_ref(|buf| buf), + // fake a null terminator + null(), + ]; + let expected_arr = [ + one, two, three + ]; + + let arr_ptr = arr.as_ptr(); + let mut ctr = 0; + let mut iteration_count = 0; + array_each(arr_ptr, |e| { + let actual = str::raw::from_c_str(e); + let expected = expected_arr[ctr].with_ref(|buf| { + str::raw::from_c_str(buf) + }); + debug!( + "test_ptr_array_each e: {}, a: {}", + expected, actual); + assert_eq!(actual, expected); + ctr += 1; + iteration_count += 1; + }); + assert_eq!(iteration_count, 3); + } + } + + #[test] + #[should_fail] + fn test_ptr_array_each_with_len_null_ptr() { + unsafe { + array_each_with_len(0 as **libc::c_char, 1, |e| { + str::raw::from_c_str(e); + }); + } + } + #[test] + #[should_fail] + fn test_ptr_array_each_null_ptr() { + unsafe { + array_each(0 as **libc::c_char, |e| { + str::raw::from_c_str(e); + }); + } + } + + #[test] + fn test_set_memory() { + let mut xs = [0u8, ..20]; + let ptr = xs.as_mut_ptr(); + unsafe { set_memory(ptr, 5u8, xs.len()); } + assert!(xs == [5u8, ..20]); + } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 9ef657f6e4a..1405d201a52 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -135,6 +135,7 @@ extern crate core; pub use core::intrinsics; pub use core::mem; +pub use core::ptr; // Run tests with libgreen instead of libnative. // @@ -191,7 +192,7 @@ pub mod strbuf; pub mod ascii; -pub mod ptr; +pub mod owned; mod managed; mod reference; pub mod rc; diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs deleted file mode 100644 index dac727c2aa4..00000000000 --- a/src/libstd/ptr.rs +++ /dev/null @@ -1,772 +0,0 @@ -// Copyright 2012-2013 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. - -//! Conveniences for working with unsafe pointers, the `*T`, and `*mut T` types. -//! -//! Working with unsafe pointers in Rust is fairly uncommon, -//! and often limited to some narrow use cases: holding -//! an unsafe pointer when safe pointers are unsuitable; -//! checking for null; and converting back to safe pointers. -//! As a result, there is not yet an abundance of library code -//! for working with unsafe pointers, and in particular, -//! since pointer math is fairly uncommon in Rust, it is not -//! all that convenient. -//! -//! Use the [`null` function](fn.null.html) to create null pointers, -//! the [`is_null`](trait.RawPtr.html#tymethod.is_null) -//! and [`is_not_null`](trait.RawPtr.html#method.is_not_null) -//! methods of the [`RawPtr` trait](trait.RawPtr.html) to check for null. -//! The `RawPtr` trait is imported by the prelude, so `is_null` etc. -//! work everywhere. -//! -//! # Common ways to create unsafe pointers -//! -//! ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`). -//! -//! ``` -//! let my_num: int = 10; -//! let my_num_ptr: *int = &my_num; -//! let mut my_speed: int = 88; -//! let my_speed_ptr: *mut int = &mut my_speed; -//! ``` -//! -//! This does not take ownership of the original allocation -//! and requires no resource management later, -//! but you must not use the pointer after its lifetime. -//! -//! ## 2. Transmute an owned box (`Box`). -//! -//! The `transmute` function takes, by value, whatever it's given -//! and returns it as whatever type is requested, as long as the -//! types are the same size. Because `Box` and `*T` have the same -//! representation they can be trivially, -//! though unsafely, transformed from one type to the other. -//! -//! ``` -//! use std::cast; -//! -//! unsafe { -//! let my_num: Box = box 10; -//! let my_num: *int = cast::transmute(my_num); -//! let my_speed: Box = box 88; -//! let my_speed: *mut int = cast::transmute(my_speed); -//! -//! // By taking ownership of the original `Box` though -//! // we are obligated to transmute it back later to be destroyed. -//! drop(cast::transmute::<_, Box>(my_speed)); -//! drop(cast::transmute::<_, Box>(my_num)); -//! } -//! ``` -//! -//! Note that here the call to `drop` is for clarity - it indicates -//! that we are done with the given value and it should be destroyed. -//! -//! ## 3. Get it from C. -//! -//! ``` -//! extern crate libc; -//! -//! use std::mem; -//! -//! fn main() { -//! unsafe { -//! let my_num: *mut int = libc::malloc(mem::size_of::() as libc::size_t) as *mut int; -//! if my_num.is_null() { -//! fail!("failed to allocate memory"); -//! } -//! libc::free(my_num as *mut libc::c_void); -//! } -//! } -//! ``` -//! -//! Usually you wouldn't literally use `malloc` and `free` from Rust, -//! but C APIs hand out a lot of pointers generally, so are a common source -//! of unsafe pointers in Rust. - -use cast; -use clone::Clone; -#[cfg(not(test))] -use cmp::Equiv; -use iter::{range, Iterator}; -use mem; -use option::{Option, Some, None}; -use intrinsics; - -#[cfg(not(test))] use cmp::{Eq, TotalEq, Ord}; - -/// Return the offset of the first null pointer in `buf`. -#[inline] -pub unsafe fn buf_len(buf: **T) -> uint { - position(buf, |i| *i == null()) -} - -impl Clone for *T { - #[inline] - fn clone(&self) -> *T { - *self - } -} - -impl Clone for *mut T { - #[inline] - fn clone(&self) -> *mut T { - *self - } -} - -/// Return the first offset `i` such that `f(buf[i]) == true`. -#[inline] -pub unsafe fn position(buf: *T, f: |&T| -> bool) -> uint { - let mut i = 0; - loop { - if f(&(*buf.offset(i as int))) { return i; } - else { i += 1; } - } -} - -/// Create a null pointer. -/// -/// # Example -/// -/// ``` -/// use std::ptr; -/// -/// let p: *int = ptr::null(); -/// assert!(p.is_null()); -/// ``` -#[inline] -pub fn null() -> *T { 0 as *T } - -/// Create an unsafe mutable null pointer. -/// -/// # Example -/// -/// ``` -/// use std::ptr; -/// -/// let p: *mut int = ptr::mut_null(); -/// assert!(p.is_null()); -/// ``` -#[inline] -pub fn mut_null() -> *mut T { 0 as *mut T } - -/// Copies data from one location to another. -/// -/// Copies `count` elements (not bytes) from `src` to `dst`. The source -/// and destination may overlap. -/// -/// `copy_memory` is semantically equivalent to C's `memmove`. -/// -/// # Example -/// -/// Efficiently create a Rust vector from an unsafe buffer: -/// -/// ``` -/// use std::ptr; -/// -/// unsafe fn from_buf_raw(ptr: *T, elts: uint) -> Vec { -/// let mut dst = Vec::with_capacity(elts); -/// dst.set_len(elts); -/// ptr::copy_memory(dst.as_mut_ptr(), ptr, elts); -/// dst -/// } -/// ``` -/// -#[inline] -pub unsafe fn copy_memory(dst: *mut T, src: *T, count: uint) { - intrinsics::copy_memory(dst, src, count) -} - -/// Copies data from one location to another. -/// -/// Copies `count` elements (not bytes) from `src` to `dst`. The source -/// and destination may *not* overlap. -/// -/// `copy_nonoverlapping_memory` is semantically equivalent to C's `memcpy`. -/// -/// # Example -/// -/// A safe swap function: -/// -/// ``` -/// use std::cast; -/// use std::mem; -/// use std::ptr; -/// -/// fn swap(x: &mut T, y: &mut T) { -/// unsafe { -/// // Give ourselves some scratch space to work with -/// let mut t: T = mem::uninit(); -/// -/// // Perform the swap, `&mut` pointers never alias -/// ptr::copy_nonoverlapping_memory(&mut t, &*x, 1); -/// ptr::copy_nonoverlapping_memory(x, &*y, 1); -/// ptr::copy_nonoverlapping_memory(y, &t, 1); -/// -/// // y and t now point to the same thing, but we need to completely forget `tmp` -/// // because it's no longer relevant. -/// cast::forget(t); -/// } -/// } -/// ``` -/// -/// # Safety Note -/// -/// If the source and destination overlap then the behavior of this -/// function is undefined. -#[inline] -pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, - src: *T, - count: uint) { - intrinsics::copy_nonoverlapping_memory(dst, src, count) -} - -/// Invokes memset on the specified pointer, setting `count * size_of::()` -/// bytes of memory starting at `dst` to `c`. -#[inline] -pub unsafe fn set_memory(dst: *mut T, c: u8, count: uint) { - intrinsics::set_memory(dst, c, count) -} - -/// Zeroes out `count * size_of::` bytes of memory at `dst` -#[inline] -pub unsafe fn zero_memory(dst: *mut T, count: uint) { - set_memory(dst, 0, count); -} - -/// Swap the values at two mutable locations of the same type, without -/// deinitialising either. They may overlap. -#[inline] -pub unsafe fn swap(x: *mut T, y: *mut T) { - // Give ourselves some scratch space to work with - let mut tmp: T = mem::uninit(); - let t: *mut T = &mut tmp; - - // Perform the swap - copy_nonoverlapping_memory(t, &*x, 1); - copy_memory(x, &*y, 1); // `x` and `y` may overlap - copy_nonoverlapping_memory(y, &*t, 1); - - // y and t now point to the same thing, but we need to completely forget `tmp` - // because it's no longer relevant. - cast::forget(tmp); -} - -/// Replace the value at a mutable location with a new one, returning the old -/// value, without deinitialising either. -#[inline] -pub unsafe fn replace(dest: *mut T, mut src: T) -> T { - mem::swap(cast::transmute(dest), &mut src); // cannot overlap - src -} - -/// Reads the value from `*src` and returns it. -#[inline(always)] -pub unsafe fn read(src: *T) -> T { - let mut tmp: T = mem::uninit(); - copy_nonoverlapping_memory(&mut tmp, src, 1); - tmp -} - -/// Reads the value from `*src` and nulls it out. -/// This currently prevents destructors from executing. -#[inline(always)] -pub unsafe fn read_and_zero(dest: *mut T) -> T { - // Copy the data out from `dest`: - let tmp = read(&*dest); - - // Now zero out `dest`: - zero_memory(dest, 1); - - tmp -} - -/// Given a **T (pointer to an array of pointers), -/// iterate through each *T, up to the provided `len`, -/// passing to the provided callback function -pub unsafe fn array_each_with_len(arr: **T, len: uint, cb: |*T|) { - if arr.is_null() { - fail!("ptr::array_each_with_len failure: arr input is null pointer"); - } - //let start_ptr = *arr; - for e in range(0, len) { - let n = arr.offset(e as int); - cb(*n); - } -} - -/// Given a null-pointer-terminated **T (pointer to -/// an array of pointers), iterate through each *T, -/// passing to the provided callback function -/// -/// # Safety Note -/// -/// This will only work with a null-terminated -/// pointer array. -pub unsafe fn array_each(arr: **T, cb: |*T|) { - if arr.is_null() { - fail!("ptr::array_each_with_len failure: arr input is null pointer"); - } - let len = buf_len(arr); - array_each_with_len(arr, len, cb); -} - -/// Extension methods for raw pointers. -pub trait RawPtr { - /// Returns the null pointer. - fn null() -> Self; - /// Returns true if the pointer is equal to the null pointer. - fn is_null(&self) -> bool; - /// Returns true if the pointer is not equal to the null pointer. - fn is_not_null(&self) -> bool { !self.is_null() } - /// Returns the value of this pointer (ie, the address it points to) - fn to_uint(&self) -> uint; - /// Returns `None` if the pointer is null, or else returns the value wrapped - /// in `Some`. - /// - /// # Safety Notes - /// - /// While this method is 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. - unsafe fn to_option(&self) -> Option<&T>; - /// Calculates the offset from a pointer. The offset *must* be in-bounds of - /// the object, or one-byte-past-the-end. `count` is in units of T; e.g. a - /// `count` of 3 represents a pointer offset of `3 * sizeof::()` bytes. - unsafe fn offset(self, count: int) -> Self; -} - -impl RawPtr for *T { - #[inline] - fn null() -> *T { null() } - - #[inline] - fn is_null(&self) -> bool { *self == RawPtr::null() } - - #[inline] - fn to_uint(&self) -> uint { *self as uint } - - #[inline] - unsafe fn offset(self, count: int) -> *T { intrinsics::offset(self, count) } - - #[inline] - unsafe fn to_option(&self) -> Option<&T> { - if self.is_null() { - None - } else { - Some(cast::transmute(*self)) - } - } -} - -impl RawPtr for *mut T { - #[inline] - fn null() -> *mut T { mut_null() } - - #[inline] - fn is_null(&self) -> bool { *self == RawPtr::null() } - - #[inline] - fn to_uint(&self) -> uint { *self as uint } - - #[inline] - unsafe fn offset(self, count: int) -> *mut T { intrinsics::offset(self as *T, count) as *mut T } - - #[inline] - unsafe fn to_option(&self) -> Option<&T> { - if self.is_null() { - None - } else { - Some(cast::transmute(*self)) - } - } -} - -// Equality for pointers -#[cfg(not(test))] -impl Eq for *T { - #[inline] - fn eq(&self, other: &*T) -> bool { - *self == *other - } - #[inline] - fn ne(&self, other: &*T) -> bool { !self.eq(other) } -} - -#[cfg(not(test))] -impl TotalEq for *T {} - -#[cfg(not(test))] -impl Eq for *mut T { - #[inline] - fn eq(&self, other: &*mut T) -> bool { - *self == *other - } - #[inline] - fn ne(&self, other: &*mut T) -> bool { !self.eq(other) } -} - -#[cfg(not(test))] -impl TotalEq for *mut T {} - -// Equivalence for pointers -#[cfg(not(test))] -impl Equiv<*mut T> for *T { - fn equiv(&self, other: &*mut T) -> bool { - self.to_uint() == other.to_uint() - } -} - -#[cfg(not(test))] -impl Equiv<*T> for *mut T { - fn equiv(&self, other: &*T) -> bool { - self.to_uint() == other.to_uint() - } -} - -// Equality for extern "C" fn pointers -#[cfg(not(test))] -mod externfnpointers { - use cast; - use cmp::Eq; - - impl<_R> Eq for extern "C" fn() -> _R { - #[inline] - fn eq(&self, other: &extern "C" fn() -> _R) -> bool { - let self_: *() = unsafe { cast::transmute(*self) }; - let other_: *() = unsafe { cast::transmute(*other) }; - self_ == other_ - } - #[inline] - fn ne(&self, other: &extern "C" fn() -> _R) -> bool { - !self.eq(other) - } - } - macro_rules! fnptreq( - ($($p:ident),*) => { - impl<_R,$($p),*> Eq for extern "C" fn($($p),*) -> _R { - #[inline] - fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool { - let self_: *() = unsafe { cast::transmute(*self) }; - let other_: *() = unsafe { cast::transmute(*other) }; - self_ == other_ - } - #[inline] - fn ne(&self, other: &extern "C" fn($($p),*) -> _R) -> bool { - !self.eq(other) - } - } - } - ) - fnptreq!(A) - fnptreq!(A,B) - fnptreq!(A,B,C) - fnptreq!(A,B,C,D) - fnptreq!(A,B,C,D,E) -} - -// Comparison for pointers -#[cfg(not(test))] -impl Ord for *T { - #[inline] - fn lt(&self, other: &*T) -> bool { - *self < *other - } - #[inline] - fn le(&self, other: &*T) -> bool { - *self <= *other - } - #[inline] - fn ge(&self, other: &*T) -> bool { - *self >= *other - } - #[inline] - fn gt(&self, other: &*T) -> bool { - *self > *other - } -} - -#[cfg(not(test))] -impl Ord for *mut T { - #[inline] - fn lt(&self, other: &*mut T) -> bool { - *self < *other - } - #[inline] - fn le(&self, other: &*mut T) -> bool { - *self <= *other - } - #[inline] - fn ge(&self, other: &*mut T) -> bool { - *self >= *other - } - #[inline] - fn gt(&self, other: &*mut T) -> bool { - *self > *other - } -} - -#[cfg(test)] -pub mod ptr_tests { - use super::*; - use prelude::*; - - use c_str::ToCStr; - use cast; - use libc; - use str; - use slice::{ImmutableVector, MutableVector}; - - #[test] - fn test() { - unsafe { - struct Pair { - fst: int, - snd: int - }; - let mut p = Pair {fst: 10, snd: 20}; - let pptr: *mut Pair = &mut p; - let iptr: *mut int = cast::transmute(pptr); - assert_eq!(*iptr, 10); - *iptr = 30; - assert_eq!(*iptr, 30); - assert_eq!(p.fst, 30); - - *pptr = Pair {fst: 50, snd: 60}; - assert_eq!(*iptr, 50); - assert_eq!(p.fst, 50); - assert_eq!(p.snd, 60); - - let v0 = box [32000u16, 32001u16, 32002u16]; - let mut v1 = box [0u16, 0u16, 0u16]; - - copy_memory(v1.as_mut_ptr().offset(1), - v0.as_ptr().offset(1), 1); - assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16)); - copy_memory(v1.as_mut_ptr(), - v0.as_ptr().offset(2), 1); - assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && - v1[2] == 0u16)); - copy_memory(v1.as_mut_ptr().offset(2), - v0.as_ptr(), 1u); - assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && - v1[2] == 32000u16)); - } - } - - #[test] - fn test_position() { - use libc::c_char; - - "hello".with_c_str(|p| { - unsafe { - assert!(2u == position(p, |c| *c == 'l' as c_char)); - assert!(4u == position(p, |c| *c == 'o' as c_char)); - assert!(5u == position(p, |c| *c == 0 as c_char)); - } - }) - } - - #[test] - fn test_buf_len() { - "hello".with_c_str(|p0| { - "there".with_c_str(|p1| { - "thing".with_c_str(|p2| { - let v = box [p0, p1, p2, null()]; - unsafe { - assert_eq!(buf_len(v.as_ptr()), 3u); - } - }) - }) - }) - } - - #[test] - fn test_is_null() { - let p: *int = null(); - assert!(p.is_null()); - assert!(!p.is_not_null()); - - let q = unsafe { p.offset(1) }; - assert!(!q.is_null()); - assert!(q.is_not_null()); - - let mp: *mut int = mut_null(); - assert!(mp.is_null()); - assert!(!mp.is_not_null()); - - let mq = unsafe { mp.offset(1) }; - assert!(!mq.is_null()); - assert!(mq.is_not_null()); - } - - #[test] - fn test_to_option() { - unsafe { - let p: *int = null(); - assert_eq!(p.to_option(), None); - - let q: *int = &2; - assert_eq!(q.to_option().unwrap(), &2); - - let p: *mut int = mut_null(); - assert_eq!(p.to_option(), None); - - let q: *mut int = &mut 2; - assert_eq!(q.to_option().unwrap(), &2); - } - } - - #[test] - fn test_ptr_addition() { - unsafe { - let xs = box [5, ..16]; - let mut ptr = xs.as_ptr(); - let end = ptr.offset(16); - - while ptr < end { - assert_eq!(*ptr, 5); - ptr = ptr.offset(1); - } - - let mut xs_mut = xs.clone(); - let mut m_ptr = xs_mut.as_mut_ptr(); - let m_end = m_ptr.offset(16); - - while m_ptr < m_end { - *m_ptr += 5; - m_ptr = m_ptr.offset(1); - } - - assert_eq!(xs_mut, box [10, ..16]); - } - } - - #[test] - fn test_ptr_subtraction() { - unsafe { - let xs = box [0,1,2,3,4,5,6,7,8,9]; - let mut idx = 9i8; - let ptr = xs.as_ptr(); - - while idx >= 0i8 { - assert_eq!(*(ptr.offset(idx as int)), idx as int); - idx = idx - 1i8; - } - - let mut xs_mut = xs.clone(); - let m_start = xs_mut.as_mut_ptr(); - let mut m_ptr = m_start.offset(9); - - while m_ptr >= m_start { - *m_ptr += *m_ptr; - m_ptr = m_ptr.offset(-1); - } - - assert_eq!(xs_mut, box [0,2,4,6,8,10,12,14,16,18]); - } - } - - #[test] - fn test_ptr_array_each_with_len() { - unsafe { - let one = "oneOne".to_c_str(); - let two = "twoTwo".to_c_str(); - let three = "threeThree".to_c_str(); - let arr = box [ - one.with_ref(|buf| buf), - two.with_ref(|buf| buf), - three.with_ref(|buf| buf), - ]; - let expected_arr = [ - one, two, three - ]; - - let mut ctr = 0; - let mut iteration_count = 0; - array_each_with_len(arr.as_ptr(), arr.len(), |e| { - let actual = str::raw::from_c_str(e); - let expected = expected_arr[ctr].with_ref(|buf| { - str::raw::from_c_str(buf) - }); - debug!( - "test_ptr_array_each_with_len e: {}, a: {}", - expected, actual); - assert_eq!(actual, expected); - ctr += 1; - iteration_count += 1; - }); - assert_eq!(iteration_count, 3u); - } - } - - #[test] - fn test_ptr_array_each() { - unsafe { - let one = "oneOne".to_c_str(); - let two = "twoTwo".to_c_str(); - let three = "threeThree".to_c_str(); - let arr = box [ - one.with_ref(|buf| buf), - two.with_ref(|buf| buf), - three.with_ref(|buf| buf), - // fake a null terminator - null(), - ]; - let expected_arr = [ - one, two, three - ]; - - let arr_ptr = arr.as_ptr(); - let mut ctr = 0; - let mut iteration_count = 0; - array_each(arr_ptr, |e| { - let actual = str::raw::from_c_str(e); - let expected = expected_arr[ctr].with_ref(|buf| { - str::raw::from_c_str(buf) - }); - debug!( - "test_ptr_array_each e: {}, a: {}", - expected, actual); - assert_eq!(actual, expected); - ctr += 1; - iteration_count += 1; - }); - assert_eq!(iteration_count, 3); - } - } - - #[test] - #[should_fail] - fn test_ptr_array_each_with_len_null_ptr() { - unsafe { - array_each_with_len(0 as **libc::c_char, 1, |e| { - str::raw::from_c_str(e); - }); - } - } - #[test] - #[should_fail] - fn test_ptr_array_each_null_ptr() { - unsafe { - array_each(0 as **libc::c_char, |e| { - str::raw::from_c_str(e); - }); - } - } - - #[test] - fn test_set_memory() { - let mut xs = [0u8, ..20]; - let ptr = xs.as_mut_ptr(); - unsafe { set_memory(ptr, 5u8, xs.len()); } - assert!(xs == [5u8, ..20]); - } -} -- cgit 1.4.1-3-g733a5 From 28624661c3ab16331d134fdbbfb2fd10513e9411 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:20:44 -0700 Subject: core: Inherit the cast module --- src/libcore/cast.rs | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 1 + src/libstd/cast.rs | 149 ---------------------------------------------------- src/libstd/lib.rs | 2 +- 4 files changed, 151 insertions(+), 150 deletions(-) create mode 100644 src/libcore/cast.rs delete mode 100644 src/libstd/cast.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/cast.rs b/src/libcore/cast.rs new file mode 100644 index 00000000000..7a8f517bbf9 --- /dev/null +++ b/src/libcore/cast.rs @@ -0,0 +1,149 @@ +// 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. + +//! Unsafe casting functions + +use mem; +use intrinsics; +use ptr::copy_nonoverlapping_memory; + +/// Casts the value at `src` to U. The two types must have the same length. +#[inline] +pub unsafe fn transmute_copy(src: &T) -> U { + let mut dest: U = mem::uninit(); + let dest_ptr: *mut u8 = transmute(&mut dest); + let src_ptr: *u8 = transmute(src); + copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::()); + dest +} + +/** + * Move a thing into the void + * + * The forget function will take ownership of the provided value but neglect + * to run any required cleanup or memory-management operations on it. + */ +#[inline] +pub unsafe fn forget(thing: T) { intrinsics::forget(thing); } + +/** + * Force-increment the reference count on a shared box. If used + * carelessly, this can leak the box. + */ +#[inline] +pub unsafe fn bump_box_refcount(t: @T) { forget(t); } + +/** + * Transform a value of one type into a value of another type. + * Both types must have the same size and alignment. + * + * # Example + * + * ```rust + * use std::cast; + * + * let v: &[u8] = unsafe { cast::transmute("L") }; + * assert!(v == [76u8]); + * ``` + */ +#[inline] +pub unsafe fn transmute(thing: L) -> G { + intrinsics::transmute(thing) +} + +/// Coerce an immutable reference to be mutable. +#[inline] +#[deprecated="casting &T to &mut T is undefined behaviour: use Cell, RefCell or Unsafe"] +pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) } + +/// Coerce a reference to have an arbitrary associated lifetime. +#[inline] +pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T { + transmute(ptr) +} + +/// Coerce an immutable reference to be mutable. +#[inline] +pub unsafe fn transmute_mut_unsafe(ptr: *T) -> *mut T { + transmute(ptr) +} + +/// Coerce a mutable reference to have an arbitrary associated lifetime. +#[inline] +pub unsafe fn transmute_mut_lifetime<'a,'b,T>(ptr: &'a mut T) -> &'b mut T { + transmute(ptr) +} + +/// Transforms lifetime of the second pointer to match the first. +#[inline] +pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T { + transmute_lifetime(ptr) +} + +/// Transforms lifetime of the second pointer to match the first. +#[inline] +pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T { + transmute_mut_lifetime(ptr) +} + +/// Transforms lifetime of the second pointer to match the first. +#[inline] +pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T { + transmute_lifetime(ptr) +} + + +/**************************************************************************** + * Tests + ****************************************************************************/ + +#[cfg(test)] +mod tests { + use cast::{bump_box_refcount, transmute}; + use raw; + use str::StrSlice; + + #[test] + fn test_transmute_copy() { + assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) }); + } + + #[test] + fn test_bump_managed_refcount() { + unsafe { + let managed = @"box box box".to_owned(); // refcount 1 + bump_box_refcount(managed); // refcount 2 + let ptr: *int = transmute(managed); // refcount 2 + let _box1: @~str = ::cast::transmute_copy(&ptr); + let _box2: @~str = ::cast::transmute_copy(&ptr); + assert!(*_box1 == "box box box".to_owned()); + assert!(*_box2 == "box box box".to_owned()); + // Will destroy _box1 and _box2. Without the bump, this would + // use-after-free. With too many bumps, it would leak. + } + } + + #[test] + fn test_transmute() { + unsafe { + let x = @100u8; + let x: *raw::Box = transmute(x); + assert!((*x).data == 100); + let _x: @int = transmute(x); + } + } + + #[test] + fn test_transmute2() { + unsafe { + assert_eq!(box [76u8], transmute("L".to_owned())); + } + } +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index bbbadad6e36..4f215793a38 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -23,6 +23,7 @@ /* Core modules for ownership management */ +pub mod cast; pub mod intrinsics; pub mod mem; pub mod ptr; diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs deleted file mode 100644 index 7a8f517bbf9..00000000000 --- a/src/libstd/cast.rs +++ /dev/null @@ -1,149 +0,0 @@ -// 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. - -//! Unsafe casting functions - -use mem; -use intrinsics; -use ptr::copy_nonoverlapping_memory; - -/// Casts the value at `src` to U. The two types must have the same length. -#[inline] -pub unsafe fn transmute_copy(src: &T) -> U { - let mut dest: U = mem::uninit(); - let dest_ptr: *mut u8 = transmute(&mut dest); - let src_ptr: *u8 = transmute(src); - copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::()); - dest -} - -/** - * Move a thing into the void - * - * The forget function will take ownership of the provided value but neglect - * to run any required cleanup or memory-management operations on it. - */ -#[inline] -pub unsafe fn forget(thing: T) { intrinsics::forget(thing); } - -/** - * Force-increment the reference count on a shared box. If used - * carelessly, this can leak the box. - */ -#[inline] -pub unsafe fn bump_box_refcount(t: @T) { forget(t); } - -/** - * Transform a value of one type into a value of another type. - * Both types must have the same size and alignment. - * - * # Example - * - * ```rust - * use std::cast; - * - * let v: &[u8] = unsafe { cast::transmute("L") }; - * assert!(v == [76u8]); - * ``` - */ -#[inline] -pub unsafe fn transmute(thing: L) -> G { - intrinsics::transmute(thing) -} - -/// Coerce an immutable reference to be mutable. -#[inline] -#[deprecated="casting &T to &mut T is undefined behaviour: use Cell, RefCell or Unsafe"] -pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) } - -/// Coerce a reference to have an arbitrary associated lifetime. -#[inline] -pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T { - transmute(ptr) -} - -/// Coerce an immutable reference to be mutable. -#[inline] -pub unsafe fn transmute_mut_unsafe(ptr: *T) -> *mut T { - transmute(ptr) -} - -/// Coerce a mutable reference to have an arbitrary associated lifetime. -#[inline] -pub unsafe fn transmute_mut_lifetime<'a,'b,T>(ptr: &'a mut T) -> &'b mut T { - transmute(ptr) -} - -/// Transforms lifetime of the second pointer to match the first. -#[inline] -pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T { - transmute_lifetime(ptr) -} - -/// Transforms lifetime of the second pointer to match the first. -#[inline] -pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T { - transmute_mut_lifetime(ptr) -} - -/// Transforms lifetime of the second pointer to match the first. -#[inline] -pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T { - transmute_lifetime(ptr) -} - - -/**************************************************************************** - * Tests - ****************************************************************************/ - -#[cfg(test)] -mod tests { - use cast::{bump_box_refcount, transmute}; - use raw; - use str::StrSlice; - - #[test] - fn test_transmute_copy() { - assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) }); - } - - #[test] - fn test_bump_managed_refcount() { - unsafe { - let managed = @"box box box".to_owned(); // refcount 1 - bump_box_refcount(managed); // refcount 2 - let ptr: *int = transmute(managed); // refcount 2 - let _box1: @~str = ::cast::transmute_copy(&ptr); - let _box2: @~str = ::cast::transmute_copy(&ptr); - assert!(*_box1 == "box box box".to_owned()); - assert!(*_box2 == "box box box".to_owned()); - // Will destroy _box1 and _box2. Without the bump, this would - // use-after-free. With too many bumps, it would leak. - } - } - - #[test] - fn test_transmute() { - unsafe { - let x = @100u8; - let x: *raw::Box = transmute(x); - assert!((*x).data == 100); - let _x: @int = transmute(x); - } - } - - #[test] - fn test_transmute2() { - unsafe { - assert_eq!(box [76u8], transmute("L".to_owned())); - } - } -} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 1405d201a52..066886ba382 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -133,6 +133,7 @@ extern crate core; #[cfg(test)] pub use ty = realstd::ty; #[cfg(test)] pub use owned = realstd::owned; +pub use core::cast; pub use core::intrinsics; pub use core::mem; pub use core::ptr; @@ -242,7 +243,6 @@ pub mod c_vec; pub mod os; pub mod io; pub mod path; -pub mod cast; pub mod fmt; pub mod cleanup; -- cgit 1.4.1-3-g733a5 From ec8a805b6dafc78e692b0a0f8de1a56c5f0dcc0f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:22:55 -0700 Subject: core: Inherit the kinds module --- src/libcore/kinds.rs | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 4 + src/libstd/kinds.rs | 281 --------------------------------------------------- src/libstd/lib.rs | 3 +- 4 files changed, 287 insertions(+), 282 deletions(-) create mode 100644 src/libcore/kinds.rs delete mode 100644 src/libstd/kinds.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/kinds.rs b/src/libcore/kinds.rs new file mode 100644 index 00000000000..6ef71d3360a --- /dev/null +++ b/src/libcore/kinds.rs @@ -0,0 +1,281 @@ +// 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. + +/*! +Primitive traits representing basic 'kinds' of types + +Rust types can be classified in various useful ways according to +intrinsic properties of the type. These classifications, often called +'kinds', are represented as traits. + +They cannot be implemented by user code, but are instead implemented +by the compiler automatically for the types to which they apply. + +*/ + +/// Types able to be transferred across task boundaries. +#[lang="send"] +pub trait Send { + // empty. +} + +/// Types with a constant size known at compile-time. +#[lang="sized"] +pub trait Sized { + // Empty. +} + +/// Types that can be copied by simply copying bits (i.e. `memcpy`). +#[lang="copy"] +pub trait Copy { + // Empty. +} + +/// Types that can be safely shared between tasks when aliased. +/// +/// The precise definition is: a type `T` is `Share` if `&T` is +/// thread-safe. In other words, there is no possibility of data races +/// when passing `&T` references between tasks. +/// +/// As one would expect, primitive types like `u8` and `f64` are all +/// `Share`, and so are simple aggregate types containing them (like +/// tuples, structs and enums). More instances of basic `Share` types +/// include "immutable" types like `&T` and those with simple +/// inherited mutability, such as `Box`, `Vec` and most other +/// collection types. (Generic parameters need to be `Share` for their +/// container to be `Share`.) +/// +/// A somewhat surprising consequence of the definition is `&mut T` is +/// `Share` (if `T` is `Share`) even though it seems that it might +/// provide unsynchronised mutation. The trick is a mutable reference +/// stored in an aliasable reference (that is, `& &mut T`) becomes +/// read-only, as if it were a `& &T`, hence there is no risk of a data +/// race. +/// +/// Types that are not `Share` are those that have "interior +/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell` +/// in `std::cell`. These types allow for mutation of their contents +/// even when in an immutable, aliasable slot, e.g. the contents of +/// `&Cell` can be `.set`, and do not ensure data races are +/// impossible, hence they cannot be `Share`. A higher level example +/// of a non-`Share` type is the reference counted pointer +/// `std::rc::Rc`, because any reference `&Rc` can clone a new +/// reference, which modifies the reference counts in a non-atomic +/// way. +/// +/// For cases when one does need thread-safe interior mutability, +/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in +/// the `sync` crate do ensure that any mutation cannot cause data +/// races. Hence these types are `Share`. +/// +/// Users writing their own types with interior mutability (or anything +/// else that is not thread-safe) should use the `NoShare` marker type +/// (from `std::kinds::marker`) to ensure that the compiler doesn't +/// consider the user-defined type to be `Share`. Any types with +/// interior mutability must also use the `std::ty::Unsafe` wrapper +/// around the value(s) which can be mutated when behind a `&` +/// reference; not doing this is undefined behaviour (for example, +/// `transmute`-ing from `&T` to `&mut T` is illegal). +#[lang="share"] +pub trait Share { + // Empty +} + +/// Marker types are special types that are used with unsafe code to +/// inform the compiler of special constraints. Marker types should +/// only be needed when you are creating an abstraction that is +/// implemented using unsafe code. In that case, you may want to embed +/// some of the marker types below into your type. +pub mod marker { + + /// A marker type whose type parameter `T` is considered to be + /// covariant with respect to the type itself. This is (typically) + /// used to indicate that an instance of the type `T` is being stored + /// into memory and read from, even though that may not be apparent. + /// + /// For more information about variance, refer to this Wikipedia + /// article . + /// + /// *Note:* It is very unusual to have to add a covariant constraint. + /// If you are not sure, you probably want to use `InvariantType`. + /// + /// # Example + /// + /// Given a struct `S` that includes a type parameter `T` + /// but does not actually *reference* that type parameter: + /// + /// ```ignore + /// use std::cast; + /// + /// struct S { x: *() } + /// fn get(s: &S) -> T { + /// unsafe { + /// let x: *T = cast::transmute(s.x); + /// *x + /// } + /// } + /// ``` + /// + /// The type system would currently infer that the value of + /// the type parameter `T` is irrelevant, and hence a `S` is + /// a subtype of `S<~[int]>` (or, for that matter, `S` for + /// any `U`). But this is incorrect because `get()` converts the + /// `*()` into a `*T` and reads from it. Therefore, we should include the + /// a marker field `CovariantType` to inform the type checker that + /// `S` is a subtype of `S` if `T` is a subtype of `U` + /// (for example, `S<&'static int>` is a subtype of `S<&'a int>` + /// for some lifetime `'a`, but not the other way around). + #[lang="covariant_type"] + #[deriving(Eq,Clone)] + pub struct CovariantType; + + /// A marker type whose type parameter `T` is considered to be + /// contravariant with respect to the type itself. This is (typically) + /// used to indicate that an instance of the type `T` will be consumed + /// (but not read from), even though that may not be apparent. + /// + /// For more information about variance, refer to this Wikipedia + /// article . + /// + /// *Note:* It is very unusual to have to add a contravariant constraint. + /// If you are not sure, you probably want to use `InvariantType`. + /// + /// # Example + /// + /// Given a struct `S` that includes a type parameter `T` + /// but does not actually *reference* that type parameter: + /// + /// ``` + /// use std::cast; + /// + /// struct S { x: *() } + /// fn get(s: &S, v: T) { + /// unsafe { + /// let x: fn(T) = cast::transmute(s.x); + /// x(v) + /// } + /// } + /// ``` + /// + /// The type system would currently infer that the value of + /// the type parameter `T` is irrelevant, and hence a `S` is + /// a subtype of `S<~[int]>` (or, for that matter, `S` for + /// any `U`). But this is incorrect because `get()` converts the + /// `*()` into a `fn(T)` and then passes a value of type `T` to it. + /// + /// Supplying a `ContravariantType` marker would correct the + /// problem, because it would mark `S` so that `S` is only a + /// subtype of `S` if `U` is a subtype of `T`; given that the + /// function requires arguments of type `T`, it must also accept + /// arguments of type `U`, hence such a conversion is safe. + #[lang="contravariant_type"] + #[deriving(Eq,Clone)] + pub struct ContravariantType; + + /// A marker type whose type parameter `T` is considered to be + /// invariant with respect to the type itself. This is (typically) + /// used to indicate that instances of the type `T` may be read or + /// written, even though that may not be apparent. + /// + /// For more information about variance, refer to this Wikipedia + /// article . + /// + /// # Example + /// + /// The Cell type is an example which uses unsafe code to achieve + /// "interior" mutability: + /// + /// ``` + /// pub struct Cell { value: T } + /// # fn main() {} + /// ``` + /// + /// The type system would infer that `value` is only read here and + /// never written, but in fact `Cell` uses unsafe code to achieve + /// interior mutability. + #[lang="invariant_type"] + #[deriving(Eq,Clone)] + pub struct InvariantType; + + /// As `CovariantType`, but for lifetime parameters. Using + /// `CovariantLifetime<'a>` indicates that it is ok to substitute + /// a *longer* lifetime for `'a` than the one you originally + /// started with (e.g., you could convert any lifetime `'foo` to + /// `'static`). You almost certainly want `ContravariantLifetime` + /// instead, or possibly `InvariantLifetime`. The only case where + /// it would be appropriate is that you have a (type-casted, and + /// hence hidden from the type system) function pointer with a + /// signature like `fn(&'a T)` (and no other uses of `'a`). In + /// this case, it is ok to substitute a larger lifetime for `'a` + /// (e.g., `fn(&'static T)`), because the function is only + /// becoming more selective in terms of what it accepts as + /// argument. + /// + /// For more information about variance, refer to this Wikipedia + /// article . + #[lang="covariant_lifetime"] + #[deriving(Eq,Clone)] + pub struct CovariantLifetime<'a>; + + /// As `ContravariantType`, but for lifetime parameters. Using + /// `ContravariantLifetime<'a>` indicates that it is ok to + /// substitute a *shorter* lifetime for `'a` than the one you + /// originally started with (e.g., you could convert `'static` to + /// any lifetime `'foo`). This is appropriate for cases where you + /// have an unsafe pointer that is actually a pointer into some + /// memory with lifetime `'a`, and thus you want to limit the + /// lifetime of your data structure to `'a`. An example of where + /// this is used is the iterator for vectors. + /// + /// For more information about variance, refer to this Wikipedia + /// article . + #[lang="contravariant_lifetime"] + #[deriving(Eq,Clone)] + pub struct ContravariantLifetime<'a>; + + /// As `InvariantType`, but for lifetime parameters. Using + /// `InvariantLifetime<'a>` indicates that it is not ok to + /// substitute any other lifetime for `'a` besides its original + /// value. This is appropriate for cases where you have an unsafe + /// pointer that is actually a pointer into memory with lifetime `'a`, + /// and this pointer is itself stored in an inherently mutable + /// location (such as a `Cell`). + #[lang="invariant_lifetime"] + #[deriving(Eq,Clone)] + pub struct InvariantLifetime<'a>; + + /// A type which is considered "not sendable", meaning that it cannot + /// be safely sent between tasks, even if it is owned. This is + /// typically embedded in other types, such as `Gc`, to ensure that + /// their instances remain thread-local. + #[lang="no_send_bound"] + #[deriving(Eq,Clone)] + pub struct NoSend; + + /// A type which is considered "not POD", meaning that it is not + /// implicitly copyable. This is typically embedded in other types to + /// ensure that they are never copied, even if they lack a destructor. + #[lang="no_copy_bound"] + #[deriving(Eq,Clone)] + pub struct NoCopy; + + /// A type which is considered "not sharable", meaning that + /// its contents are not threadsafe, hence they cannot be + /// shared between tasks. + #[lang="no_share_bound"] + #[deriving(Eq,Clone)] + pub struct NoShare; + + /// A type which is considered managed by the GC. This is typically + /// embedded in other types. + #[lang="managed_bound"] + #[deriving(Eq,Clone)] + pub struct Managed; +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 4f215793a38..630f84f6579 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -27,3 +27,7 @@ pub mod cast; pub mod intrinsics; pub mod mem; pub mod ptr; + +/* Core language traits */ + +pub mod kinds; diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs deleted file mode 100644 index 6ef71d3360a..00000000000 --- a/src/libstd/kinds.rs +++ /dev/null @@ -1,281 +0,0 @@ -// 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. - -/*! -Primitive traits representing basic 'kinds' of types - -Rust types can be classified in various useful ways according to -intrinsic properties of the type. These classifications, often called -'kinds', are represented as traits. - -They cannot be implemented by user code, but are instead implemented -by the compiler automatically for the types to which they apply. - -*/ - -/// Types able to be transferred across task boundaries. -#[lang="send"] -pub trait Send { - // empty. -} - -/// Types with a constant size known at compile-time. -#[lang="sized"] -pub trait Sized { - // Empty. -} - -/// Types that can be copied by simply copying bits (i.e. `memcpy`). -#[lang="copy"] -pub trait Copy { - // Empty. -} - -/// Types that can be safely shared between tasks when aliased. -/// -/// The precise definition is: a type `T` is `Share` if `&T` is -/// thread-safe. In other words, there is no possibility of data races -/// when passing `&T` references between tasks. -/// -/// As one would expect, primitive types like `u8` and `f64` are all -/// `Share`, and so are simple aggregate types containing them (like -/// tuples, structs and enums). More instances of basic `Share` types -/// include "immutable" types like `&T` and those with simple -/// inherited mutability, such as `Box`, `Vec` and most other -/// collection types. (Generic parameters need to be `Share` for their -/// container to be `Share`.) -/// -/// A somewhat surprising consequence of the definition is `&mut T` is -/// `Share` (if `T` is `Share`) even though it seems that it might -/// provide unsynchronised mutation. The trick is a mutable reference -/// stored in an aliasable reference (that is, `& &mut T`) becomes -/// read-only, as if it were a `& &T`, hence there is no risk of a data -/// race. -/// -/// Types that are not `Share` are those that have "interior -/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell` -/// in `std::cell`. These types allow for mutation of their contents -/// even when in an immutable, aliasable slot, e.g. the contents of -/// `&Cell` can be `.set`, and do not ensure data races are -/// impossible, hence they cannot be `Share`. A higher level example -/// of a non-`Share` type is the reference counted pointer -/// `std::rc::Rc`, because any reference `&Rc` can clone a new -/// reference, which modifies the reference counts in a non-atomic -/// way. -/// -/// For cases when one does need thread-safe interior mutability, -/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in -/// the `sync` crate do ensure that any mutation cannot cause data -/// races. Hence these types are `Share`. -/// -/// Users writing their own types with interior mutability (or anything -/// else that is not thread-safe) should use the `NoShare` marker type -/// (from `std::kinds::marker`) to ensure that the compiler doesn't -/// consider the user-defined type to be `Share`. Any types with -/// interior mutability must also use the `std::ty::Unsafe` wrapper -/// around the value(s) which can be mutated when behind a `&` -/// reference; not doing this is undefined behaviour (for example, -/// `transmute`-ing from `&T` to `&mut T` is illegal). -#[lang="share"] -pub trait Share { - // Empty -} - -/// Marker types are special types that are used with unsafe code to -/// inform the compiler of special constraints. Marker types should -/// only be needed when you are creating an abstraction that is -/// implemented using unsafe code. In that case, you may want to embed -/// some of the marker types below into your type. -pub mod marker { - - /// A marker type whose type parameter `T` is considered to be - /// covariant with respect to the type itself. This is (typically) - /// used to indicate that an instance of the type `T` is being stored - /// into memory and read from, even though that may not be apparent. - /// - /// For more information about variance, refer to this Wikipedia - /// article . - /// - /// *Note:* It is very unusual to have to add a covariant constraint. - /// If you are not sure, you probably want to use `InvariantType`. - /// - /// # Example - /// - /// Given a struct `S` that includes a type parameter `T` - /// but does not actually *reference* that type parameter: - /// - /// ```ignore - /// use std::cast; - /// - /// struct S { x: *() } - /// fn get(s: &S) -> T { - /// unsafe { - /// let x: *T = cast::transmute(s.x); - /// *x - /// } - /// } - /// ``` - /// - /// The type system would currently infer that the value of - /// the type parameter `T` is irrelevant, and hence a `S` is - /// a subtype of `S<~[int]>` (or, for that matter, `S` for - /// any `U`). But this is incorrect because `get()` converts the - /// `*()` into a `*T` and reads from it. Therefore, we should include the - /// a marker field `CovariantType` to inform the type checker that - /// `S` is a subtype of `S` if `T` is a subtype of `U` - /// (for example, `S<&'static int>` is a subtype of `S<&'a int>` - /// for some lifetime `'a`, but not the other way around). - #[lang="covariant_type"] - #[deriving(Eq,Clone)] - pub struct CovariantType; - - /// A marker type whose type parameter `T` is considered to be - /// contravariant with respect to the type itself. This is (typically) - /// used to indicate that an instance of the type `T` will be consumed - /// (but not read from), even though that may not be apparent. - /// - /// For more information about variance, refer to this Wikipedia - /// article . - /// - /// *Note:* It is very unusual to have to add a contravariant constraint. - /// If you are not sure, you probably want to use `InvariantType`. - /// - /// # Example - /// - /// Given a struct `S` that includes a type parameter `T` - /// but does not actually *reference* that type parameter: - /// - /// ``` - /// use std::cast; - /// - /// struct S { x: *() } - /// fn get(s: &S, v: T) { - /// unsafe { - /// let x: fn(T) = cast::transmute(s.x); - /// x(v) - /// } - /// } - /// ``` - /// - /// The type system would currently infer that the value of - /// the type parameter `T` is irrelevant, and hence a `S` is - /// a subtype of `S<~[int]>` (or, for that matter, `S` for - /// any `U`). But this is incorrect because `get()` converts the - /// `*()` into a `fn(T)` and then passes a value of type `T` to it. - /// - /// Supplying a `ContravariantType` marker would correct the - /// problem, because it would mark `S` so that `S` is only a - /// subtype of `S` if `U` is a subtype of `T`; given that the - /// function requires arguments of type `T`, it must also accept - /// arguments of type `U`, hence such a conversion is safe. - #[lang="contravariant_type"] - #[deriving(Eq,Clone)] - pub struct ContravariantType; - - /// A marker type whose type parameter `T` is considered to be - /// invariant with respect to the type itself. This is (typically) - /// used to indicate that instances of the type `T` may be read or - /// written, even though that may not be apparent. - /// - /// For more information about variance, refer to this Wikipedia - /// article . - /// - /// # Example - /// - /// The Cell type is an example which uses unsafe code to achieve - /// "interior" mutability: - /// - /// ``` - /// pub struct Cell { value: T } - /// # fn main() {} - /// ``` - /// - /// The type system would infer that `value` is only read here and - /// never written, but in fact `Cell` uses unsafe code to achieve - /// interior mutability. - #[lang="invariant_type"] - #[deriving(Eq,Clone)] - pub struct InvariantType; - - /// As `CovariantType`, but for lifetime parameters. Using - /// `CovariantLifetime<'a>` indicates that it is ok to substitute - /// a *longer* lifetime for `'a` than the one you originally - /// started with (e.g., you could convert any lifetime `'foo` to - /// `'static`). You almost certainly want `ContravariantLifetime` - /// instead, or possibly `InvariantLifetime`. The only case where - /// it would be appropriate is that you have a (type-casted, and - /// hence hidden from the type system) function pointer with a - /// signature like `fn(&'a T)` (and no other uses of `'a`). In - /// this case, it is ok to substitute a larger lifetime for `'a` - /// (e.g., `fn(&'static T)`), because the function is only - /// becoming more selective in terms of what it accepts as - /// argument. - /// - /// For more information about variance, refer to this Wikipedia - /// article . - #[lang="covariant_lifetime"] - #[deriving(Eq,Clone)] - pub struct CovariantLifetime<'a>; - - /// As `ContravariantType`, but for lifetime parameters. Using - /// `ContravariantLifetime<'a>` indicates that it is ok to - /// substitute a *shorter* lifetime for `'a` than the one you - /// originally started with (e.g., you could convert `'static` to - /// any lifetime `'foo`). This is appropriate for cases where you - /// have an unsafe pointer that is actually a pointer into some - /// memory with lifetime `'a`, and thus you want to limit the - /// lifetime of your data structure to `'a`. An example of where - /// this is used is the iterator for vectors. - /// - /// For more information about variance, refer to this Wikipedia - /// article . - #[lang="contravariant_lifetime"] - #[deriving(Eq,Clone)] - pub struct ContravariantLifetime<'a>; - - /// As `InvariantType`, but for lifetime parameters. Using - /// `InvariantLifetime<'a>` indicates that it is not ok to - /// substitute any other lifetime for `'a` besides its original - /// value. This is appropriate for cases where you have an unsafe - /// pointer that is actually a pointer into memory with lifetime `'a`, - /// and this pointer is itself stored in an inherently mutable - /// location (such as a `Cell`). - #[lang="invariant_lifetime"] - #[deriving(Eq,Clone)] - pub struct InvariantLifetime<'a>; - - /// A type which is considered "not sendable", meaning that it cannot - /// be safely sent between tasks, even if it is owned. This is - /// typically embedded in other types, such as `Gc`, to ensure that - /// their instances remain thread-local. - #[lang="no_send_bound"] - #[deriving(Eq,Clone)] - pub struct NoSend; - - /// A type which is considered "not POD", meaning that it is not - /// implicitly copyable. This is typically embedded in other types to - /// ensure that they are never copied, even if they lack a destructor. - #[lang="no_copy_bound"] - #[deriving(Eq,Clone)] - pub struct NoCopy; - - /// A type which is considered "not sharable", meaning that - /// its contents are not threadsafe, hence they cannot be - /// shared between tasks. - #[lang="no_share_bound"] - #[deriving(Eq,Clone)] - pub struct NoShare; - - /// A type which is considered managed by the GC. This is typically - /// embedded in other types. - #[lang="managed_bound"] - #[deriving(Eq,Clone)] - pub struct Managed; -} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 066886ba382..350bb4bbaec 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -133,6 +133,8 @@ extern crate core; #[cfg(test)] pub use ty = realstd::ty; #[cfg(test)] pub use owned = realstd::owned; +#[cfg(not(test))] pub use kinds = core::kinds; + pub use core::cast; pub use core::intrinsics; pub use core::mem; @@ -202,7 +204,6 @@ pub mod gc; /* Core language traits */ -#[cfg(not(test))] pub mod kinds; #[cfg(not(test))] pub mod ops; #[cfg(not(test))] pub mod cmp; #[cfg(not(test))] pub mod ty; -- cgit 1.4.1-3-g733a5 From ead6e16a600526b6125ad482d5e17e1f900730ce Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:24:32 -0700 Subject: core: Inherit the ops module --- src/libcore/lib.rs | 1 + src/libcore/ops.rs | 574 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/lib.rs | 2 +- src/libstd/ops.rs | 574 ----------------------------------------------------- 4 files changed, 576 insertions(+), 575 deletions(-) create mode 100644 src/libcore/ops.rs delete mode 100644 src/libstd/ops.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 630f84f6579..42df97040f1 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -31,3 +31,4 @@ pub mod ptr; /* Core language traits */ pub mod kinds; +pub mod ops; diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs new file mode 100644 index 00000000000..4c31face2e3 --- /dev/null +++ b/src/libcore/ops.rs @@ -0,0 +1,574 @@ +// 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. + +/*! + * + * Traits representing built-in operators, useful for overloading + * + * Implementing these traits allows you to get an effect similar to + * overloading operators. + * + * The values for the right hand side of an operator are automatically + * borrowed, so `a + b` is sugar for `a.add(&b)`. + * + * All of these traits are imported by the prelude, so they are available in + * every Rust program. + * + * # Example + * + * This example creates a `Point` struct that implements `Add` and `Sub`, and then + * demonstrates adding and subtracting two `Point`s. + * + * ```rust + * struct Point { + * x: int, + * y: int + * } + * + * impl Add for Point { + * fn add(&self, other: &Point) -> Point { + * Point {x: self.x + other.x, y: self.y + other.y} + * } + * } + * + * impl Sub for Point { + * fn sub(&self, other: &Point) -> Point { + * Point {x: self.x - other.x, y: self.y - other.y} + * } + * } + * fn main() { + * println!("{:?}", Point {x: 1, y: 0} + Point {x: 2, y: 3}); + * println!("{:?}", Point {x: 1, y: 0} - Point {x: 2, y: 3}); + * } + * ``` + * + * See the documentation for each trait for a minimum implementation that prints + * something to the screen. + * + */ + +/** + * + * The `Drop` trait is used to run some code when a value goes out of scope. This + * is sometimes called a 'destructor'. + * + * # Example + * + * A trivial implementation of `Drop`. The `drop` method is called when `_x` goes + * out of scope, and therefore `main` prints `Dropping!`. + * + * ```rust + * struct HasDrop; + * + * impl Drop for HasDrop { + * fn drop(&mut self) { + * println!("Dropping!"); + * } + * } + * + * fn main() { + * let _x = HasDrop; + * } + * ``` + */ +#[lang="drop"] +pub trait Drop { + /// The `drop` method, called when the value goes out of scope. + fn drop(&mut self); +} + +/** + * + * The `Add` trait is used to specify the functionality of `+`. + * + * # Example + * + * A trivial implementation of `Add`. When `Foo + Foo` happens, it ends up + * calling `add`, and therefore, `main` prints `Adding!`. + * + * ```rust + * struct Foo; + * + * impl Add for Foo { + * fn add(&self, _rhs: &Foo) -> Foo { + * println!("Adding!"); + * *self + * } + * } + * + * fn main() { + * Foo + Foo; + * } + * ``` + */ +#[lang="add"] +pub trait Add { + /// The method for the `+` operator + fn add(&self, rhs: &RHS) -> Result; +} + +/** + * + * The `Sub` trait is used to specify the functionality of `-`. + * + * # Example + * + * A trivial implementation of `Sub`. When `Foo - Foo` happens, it ends up + * calling `sub`, and therefore, `main` prints `Subtracting!`. + * + * ```rust + * struct Foo; + * + * impl Sub for Foo { + * fn sub(&self, _rhs: &Foo) -> Foo { + * println!("Subtracting!"); + * *self + * } + * } + * + * fn main() { + * Foo - Foo; + * } + * ``` + */ +#[lang="sub"] +pub trait Sub { + /// The method for the `-` operator + fn sub(&self, rhs: &RHS) -> Result; +} + +/** + * + * The `Mul` trait is used to specify the functionality of `*`. + * + * # Example + * + * A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up + * calling `mul`, and therefore, `main` prints `Multiplying!`. + * + * ```rust + * struct Foo; + * + * impl Mul for Foo { + * fn mul(&self, _rhs: &Foo) -> Foo { + * println!("Multiplying!"); + * *self + * } + * } + * + * fn main() { + * Foo * Foo; + * } + * ``` + */ +#[lang="mul"] +pub trait Mul { + /// The method for the `*` operator + fn mul(&self, rhs: &RHS) -> Result; +} + +/** + * + * The `Div` trait is used to specify the functionality of `/`. + * + * # Example + * + * A trivial implementation of `Div`. When `Foo / Foo` happens, it ends up + * calling `div`, and therefore, `main` prints `Dividing!`. + * + * ``` + * struct Foo; + * + * impl Div for Foo { + * fn div(&self, _rhs: &Foo) -> Foo { + * println!("Dividing!"); + * *self + * } + * } + * + * fn main() { + * Foo / Foo; + * } + * ``` + */ +#[lang="div"] +pub trait Div { + /// The method for the `/` operator + fn div(&self, rhs: &RHS) -> Result; +} + +/** + * + * The `Rem` trait is used to specify the functionality of `%`. + * + * # Example + * + * A trivial implementation of `Rem`. When `Foo % Foo` happens, it ends up + * calling `rem`, and therefore, `main` prints `Remainder-ing!`. + * + * ``` + * struct Foo; + * + * impl Rem for Foo { + * fn rem(&self, _rhs: &Foo) -> Foo { + * println!("Remainder-ing!"); + * *self + * } + * } + * + * fn main() { + * Foo % Foo; + * } + * ``` + */ +#[lang="rem"] +pub trait Rem { + /// The method for the `%` operator + fn rem(&self, rhs: &RHS) -> Result; +} + +/** + * + * The `Neg` trait is used to specify the functionality of unary `-`. + * + * # Example + * + * A trivial implementation of `Neg`. When `-Foo` happens, it ends up calling + * `neg`, and therefore, `main` prints `Negating!`. + * + * ``` + * struct Foo; + * + * impl Neg for Foo { + * fn neg(&self) -> Foo { + * println!("Negating!"); + * *self + * } + * } + * + * fn main() { + * -Foo; + * } + * ``` + */ +#[lang="neg"] +pub trait Neg { + /// The method for the unary `-` operator + fn neg(&self) -> Result; +} + +/** + * + * The `Not` trait is used to specify the functionality of unary `!`. + * + * # Example + * + * A trivial implementation of `Not`. When `!Foo` happens, it ends up calling + * `not`, and therefore, `main` prints `Not-ing!`. + * + * ``` + * struct Foo; + * + * impl Not for Foo { + * fn not(&self) -> Foo { + * println!("Not-ing!"); + * *self + * } + * } + * + * fn main() { + * !Foo; + * } + * ``` + */ +#[lang="not"] +pub trait Not { + /// The method for the unary `!` operator + fn not(&self) -> Result; +} + +/** + * + * The `BitAnd` trait is used to specify the functionality of `&`. + * + * # Example + * + * A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up + * calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`. + * + * ``` + * struct Foo; + * + * impl BitAnd for Foo { + * fn bitand(&self, _rhs: &Foo) -> Foo { + * println!("Bitwise And-ing!"); + * *self + * } + * } + * + * fn main() { + * Foo & Foo; + * } + * ``` + */ +#[lang="bitand"] +pub trait BitAnd { + /// The method for the `&` operator + fn bitand(&self, rhs: &RHS) -> Result; +} + +/** + * + * The `BitOr` trait is used to specify the functionality of `|`. + * + * # Example + * + * A trivial implementation of `BitOr`. When `Foo | Foo` happens, it ends up + * calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`. + * + * ``` + * struct Foo; + * + * impl BitOr for Foo { + * fn bitor(&self, _rhs: &Foo) -> Foo { + * println!("Bitwise Or-ing!"); + * *self + * } + * } + * + * fn main() { + * Foo | Foo; + * } + * ``` + */ +#[lang="bitor"] +pub trait BitOr { + /// The method for the `|` operator + fn bitor(&self, rhs: &RHS) -> Result; +} + +/** + * + * The `BitXor` trait is used to specify the functionality of `^`. + * + * # Example + * + * A trivial implementation of `BitXor`. When `Foo ^ Foo` happens, it ends up + * calling `bitxor`, and therefore, `main` prints `Bitwise Xor-ing!`. + * + * ``` + * struct Foo; + * + * impl BitXor for Foo { + * fn bitxor(&self, _rhs: &Foo) -> Foo { + * println!("Bitwise Xor-ing!"); + * *self + * } + * } + * + * fn main() { + * Foo ^ Foo; + * } + * ``` + */ +#[lang="bitxor"] +pub trait BitXor { + /// The method for the `^` operator + fn bitxor(&self, rhs: &RHS) -> Result; +} + +/** + * + * The `Shl` trait is used to specify the functionality of `<<`. + * + * # Example + * + * A trivial implementation of `Shl`. When `Foo << Foo` happens, it ends up + * calling `shl`, and therefore, `main` prints `Shifting left!`. + * + * ``` + * struct Foo; + * + * impl Shl for Foo { + * fn shl(&self, _rhs: &Foo) -> Foo { + * println!("Shifting left!"); + * *self + * } + * } + * + * fn main() { + * Foo << Foo; + * } + * ``` + */ +#[lang="shl"] +pub trait Shl { + /// The method for the `<<` operator + fn shl(&self, rhs: &RHS) -> Result; +} + +/** + * + * The `Shr` trait is used to specify the functionality of `>>`. + * + * # Example + * + * A trivial implementation of `Shr`. When `Foo >> Foo` happens, it ends up + * calling `shr`, and therefore, `main` prints `Shifting right!`. + * + * ``` + * struct Foo; + * + * impl Shr for Foo { + * fn shr(&self, _rhs: &Foo) -> Foo { + * println!("Shifting right!"); + * *self + * } + * } + * + * fn main() { + * Foo >> Foo; + * } + * ``` + */ +#[lang="shr"] +pub trait Shr { + /// The method for the `>>` operator + fn shr(&self, rhs: &RHS) -> Result; +} + +/** + * + * The `Index` trait is used to specify the functionality of indexing operations + * like `arr[idx]`. + * + * # Example + * + * A trivial implementation of `Index`. When `Foo[Foo]` happens, it ends up + * calling `index`, and therefore, `main` prints `Indexing!`. + * + * ``` + * struct Foo; + * + * impl Index for Foo { + * fn index(&self, _rhs: &Foo) -> Foo { + * println!("Indexing!"); + * *self + * } + * } + * + * fn main() { + * Foo[Foo]; + * } + * ``` + */ +#[lang="index"] +pub trait Index { + /// The method for the indexing (`Foo[Bar]`) operation + fn index(&self, index: &Index) -> Result; +} + +/** + * + * The `Deref` trait is used to specify the functionality of dereferencing + * operations like `*v`. + * + * # Example + * + * A struct with a single field which is accessible via dereferencing the + * struct. + * + * ``` + * struct DerefExample { + * value: T + * } + * + * impl Deref for DerefExample { + * fn deref<'a>(&'a self) -> &'a T { + * &self.value + * } + * } + * + * fn main() { + * let x = DerefExample { value: 'a' }; + * assert_eq!('a', *x); + * } + * ``` + */ +#[lang="deref"] +pub trait Deref { + /// The method called to dereference a value + fn deref<'a>(&'a self) -> &'a Result; +} + +/** + * + * The `DerefMut` trait is used to specify the functionality of dereferencing + * mutably like `*v = 1;` + * + * # Example + * + * A struct with a single field which is modifiable via dereferencing the + * struct. + * + * ``` + * struct DerefMutExample { + * value: T + * } + * + * impl Deref for DerefMutExample { + * fn deref<'a>(&'a self) -> &'a T { + * &self.value + * } + * } + * + * impl DerefMut for DerefMutExample { + * fn deref_mut<'a>(&'a mut self) -> &'a mut T { + * &mut self.value + * } + * } + * + * fn main() { + * let mut x = DerefMutExample { value: 'a' }; + * *x = 'b'; + * assert_eq!('b', *x); + * } + * ``` + */ +#[lang="deref_mut"] +pub trait DerefMut: Deref { + /// The method called to mutably dereference a value + fn deref_mut<'a>(&'a mut self) -> &'a mut Result; +} + +#[cfg(test)] +mod bench { + extern crate test; + use self::test::Bencher; + use ops::Drop; + + // Overhead of dtors + + struct HasDtor { + x: int + } + + impl Drop for HasDtor { + fn drop(&mut self) { + } + } + + #[bench] + fn alloc_obj_with_dtor(b: &mut Bencher) { + b.iter(|| { + HasDtor { x : 10 }; + }) + } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 350bb4bbaec..0ef623a558f 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -134,6 +134,7 @@ extern crate core; #[cfg(test)] pub use owned = realstd::owned; #[cfg(not(test))] pub use kinds = core::kinds; +#[cfg(not(test))] pub use ops = core::ops; pub use core::cast; pub use core::intrinsics; @@ -204,7 +205,6 @@ pub mod gc; /* Core language traits */ -#[cfg(not(test))] pub mod ops; #[cfg(not(test))] pub mod cmp; #[cfg(not(test))] pub mod ty; #[cfg(not(test))] pub mod owned; diff --git a/src/libstd/ops.rs b/src/libstd/ops.rs deleted file mode 100644 index 4c31face2e3..00000000000 --- a/src/libstd/ops.rs +++ /dev/null @@ -1,574 +0,0 @@ -// 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. - -/*! - * - * Traits representing built-in operators, useful for overloading - * - * Implementing these traits allows you to get an effect similar to - * overloading operators. - * - * The values for the right hand side of an operator are automatically - * borrowed, so `a + b` is sugar for `a.add(&b)`. - * - * All of these traits are imported by the prelude, so they are available in - * every Rust program. - * - * # Example - * - * This example creates a `Point` struct that implements `Add` and `Sub`, and then - * demonstrates adding and subtracting two `Point`s. - * - * ```rust - * struct Point { - * x: int, - * y: int - * } - * - * impl Add for Point { - * fn add(&self, other: &Point) -> Point { - * Point {x: self.x + other.x, y: self.y + other.y} - * } - * } - * - * impl Sub for Point { - * fn sub(&self, other: &Point) -> Point { - * Point {x: self.x - other.x, y: self.y - other.y} - * } - * } - * fn main() { - * println!("{:?}", Point {x: 1, y: 0} + Point {x: 2, y: 3}); - * println!("{:?}", Point {x: 1, y: 0} - Point {x: 2, y: 3}); - * } - * ``` - * - * See the documentation for each trait for a minimum implementation that prints - * something to the screen. - * - */ - -/** - * - * The `Drop` trait is used to run some code when a value goes out of scope. This - * is sometimes called a 'destructor'. - * - * # Example - * - * A trivial implementation of `Drop`. The `drop` method is called when `_x` goes - * out of scope, and therefore `main` prints `Dropping!`. - * - * ```rust - * struct HasDrop; - * - * impl Drop for HasDrop { - * fn drop(&mut self) { - * println!("Dropping!"); - * } - * } - * - * fn main() { - * let _x = HasDrop; - * } - * ``` - */ -#[lang="drop"] -pub trait Drop { - /// The `drop` method, called when the value goes out of scope. - fn drop(&mut self); -} - -/** - * - * The `Add` trait is used to specify the functionality of `+`. - * - * # Example - * - * A trivial implementation of `Add`. When `Foo + Foo` happens, it ends up - * calling `add`, and therefore, `main` prints `Adding!`. - * - * ```rust - * struct Foo; - * - * impl Add for Foo { - * fn add(&self, _rhs: &Foo) -> Foo { - * println!("Adding!"); - * *self - * } - * } - * - * fn main() { - * Foo + Foo; - * } - * ``` - */ -#[lang="add"] -pub trait Add { - /// The method for the `+` operator - fn add(&self, rhs: &RHS) -> Result; -} - -/** - * - * The `Sub` trait is used to specify the functionality of `-`. - * - * # Example - * - * A trivial implementation of `Sub`. When `Foo - Foo` happens, it ends up - * calling `sub`, and therefore, `main` prints `Subtracting!`. - * - * ```rust - * struct Foo; - * - * impl Sub for Foo { - * fn sub(&self, _rhs: &Foo) -> Foo { - * println!("Subtracting!"); - * *self - * } - * } - * - * fn main() { - * Foo - Foo; - * } - * ``` - */ -#[lang="sub"] -pub trait Sub { - /// The method for the `-` operator - fn sub(&self, rhs: &RHS) -> Result; -} - -/** - * - * The `Mul` trait is used to specify the functionality of `*`. - * - * # Example - * - * A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up - * calling `mul`, and therefore, `main` prints `Multiplying!`. - * - * ```rust - * struct Foo; - * - * impl Mul for Foo { - * fn mul(&self, _rhs: &Foo) -> Foo { - * println!("Multiplying!"); - * *self - * } - * } - * - * fn main() { - * Foo * Foo; - * } - * ``` - */ -#[lang="mul"] -pub trait Mul { - /// The method for the `*` operator - fn mul(&self, rhs: &RHS) -> Result; -} - -/** - * - * The `Div` trait is used to specify the functionality of `/`. - * - * # Example - * - * A trivial implementation of `Div`. When `Foo / Foo` happens, it ends up - * calling `div`, and therefore, `main` prints `Dividing!`. - * - * ``` - * struct Foo; - * - * impl Div for Foo { - * fn div(&self, _rhs: &Foo) -> Foo { - * println!("Dividing!"); - * *self - * } - * } - * - * fn main() { - * Foo / Foo; - * } - * ``` - */ -#[lang="div"] -pub trait Div { - /// The method for the `/` operator - fn div(&self, rhs: &RHS) -> Result; -} - -/** - * - * The `Rem` trait is used to specify the functionality of `%`. - * - * # Example - * - * A trivial implementation of `Rem`. When `Foo % Foo` happens, it ends up - * calling `rem`, and therefore, `main` prints `Remainder-ing!`. - * - * ``` - * struct Foo; - * - * impl Rem for Foo { - * fn rem(&self, _rhs: &Foo) -> Foo { - * println!("Remainder-ing!"); - * *self - * } - * } - * - * fn main() { - * Foo % Foo; - * } - * ``` - */ -#[lang="rem"] -pub trait Rem { - /// The method for the `%` operator - fn rem(&self, rhs: &RHS) -> Result; -} - -/** - * - * The `Neg` trait is used to specify the functionality of unary `-`. - * - * # Example - * - * A trivial implementation of `Neg`. When `-Foo` happens, it ends up calling - * `neg`, and therefore, `main` prints `Negating!`. - * - * ``` - * struct Foo; - * - * impl Neg for Foo { - * fn neg(&self) -> Foo { - * println!("Negating!"); - * *self - * } - * } - * - * fn main() { - * -Foo; - * } - * ``` - */ -#[lang="neg"] -pub trait Neg { - /// The method for the unary `-` operator - fn neg(&self) -> Result; -} - -/** - * - * The `Not` trait is used to specify the functionality of unary `!`. - * - * # Example - * - * A trivial implementation of `Not`. When `!Foo` happens, it ends up calling - * `not`, and therefore, `main` prints `Not-ing!`. - * - * ``` - * struct Foo; - * - * impl Not for Foo { - * fn not(&self) -> Foo { - * println!("Not-ing!"); - * *self - * } - * } - * - * fn main() { - * !Foo; - * } - * ``` - */ -#[lang="not"] -pub trait Not { - /// The method for the unary `!` operator - fn not(&self) -> Result; -} - -/** - * - * The `BitAnd` trait is used to specify the functionality of `&`. - * - * # Example - * - * A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up - * calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`. - * - * ``` - * struct Foo; - * - * impl BitAnd for Foo { - * fn bitand(&self, _rhs: &Foo) -> Foo { - * println!("Bitwise And-ing!"); - * *self - * } - * } - * - * fn main() { - * Foo & Foo; - * } - * ``` - */ -#[lang="bitand"] -pub trait BitAnd { - /// The method for the `&` operator - fn bitand(&self, rhs: &RHS) -> Result; -} - -/** - * - * The `BitOr` trait is used to specify the functionality of `|`. - * - * # Example - * - * A trivial implementation of `BitOr`. When `Foo | Foo` happens, it ends up - * calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`. - * - * ``` - * struct Foo; - * - * impl BitOr for Foo { - * fn bitor(&self, _rhs: &Foo) -> Foo { - * println!("Bitwise Or-ing!"); - * *self - * } - * } - * - * fn main() { - * Foo | Foo; - * } - * ``` - */ -#[lang="bitor"] -pub trait BitOr { - /// The method for the `|` operator - fn bitor(&self, rhs: &RHS) -> Result; -} - -/** - * - * The `BitXor` trait is used to specify the functionality of `^`. - * - * # Example - * - * A trivial implementation of `BitXor`. When `Foo ^ Foo` happens, it ends up - * calling `bitxor`, and therefore, `main` prints `Bitwise Xor-ing!`. - * - * ``` - * struct Foo; - * - * impl BitXor for Foo { - * fn bitxor(&self, _rhs: &Foo) -> Foo { - * println!("Bitwise Xor-ing!"); - * *self - * } - * } - * - * fn main() { - * Foo ^ Foo; - * } - * ``` - */ -#[lang="bitxor"] -pub trait BitXor { - /// The method for the `^` operator - fn bitxor(&self, rhs: &RHS) -> Result; -} - -/** - * - * The `Shl` trait is used to specify the functionality of `<<`. - * - * # Example - * - * A trivial implementation of `Shl`. When `Foo << Foo` happens, it ends up - * calling `shl`, and therefore, `main` prints `Shifting left!`. - * - * ``` - * struct Foo; - * - * impl Shl for Foo { - * fn shl(&self, _rhs: &Foo) -> Foo { - * println!("Shifting left!"); - * *self - * } - * } - * - * fn main() { - * Foo << Foo; - * } - * ``` - */ -#[lang="shl"] -pub trait Shl { - /// The method for the `<<` operator - fn shl(&self, rhs: &RHS) -> Result; -} - -/** - * - * The `Shr` trait is used to specify the functionality of `>>`. - * - * # Example - * - * A trivial implementation of `Shr`. When `Foo >> Foo` happens, it ends up - * calling `shr`, and therefore, `main` prints `Shifting right!`. - * - * ``` - * struct Foo; - * - * impl Shr for Foo { - * fn shr(&self, _rhs: &Foo) -> Foo { - * println!("Shifting right!"); - * *self - * } - * } - * - * fn main() { - * Foo >> Foo; - * } - * ``` - */ -#[lang="shr"] -pub trait Shr { - /// The method for the `>>` operator - fn shr(&self, rhs: &RHS) -> Result; -} - -/** - * - * The `Index` trait is used to specify the functionality of indexing operations - * like `arr[idx]`. - * - * # Example - * - * A trivial implementation of `Index`. When `Foo[Foo]` happens, it ends up - * calling `index`, and therefore, `main` prints `Indexing!`. - * - * ``` - * struct Foo; - * - * impl Index for Foo { - * fn index(&self, _rhs: &Foo) -> Foo { - * println!("Indexing!"); - * *self - * } - * } - * - * fn main() { - * Foo[Foo]; - * } - * ``` - */ -#[lang="index"] -pub trait Index { - /// The method for the indexing (`Foo[Bar]`) operation - fn index(&self, index: &Index) -> Result; -} - -/** - * - * The `Deref` trait is used to specify the functionality of dereferencing - * operations like `*v`. - * - * # Example - * - * A struct with a single field which is accessible via dereferencing the - * struct. - * - * ``` - * struct DerefExample { - * value: T - * } - * - * impl Deref for DerefExample { - * fn deref<'a>(&'a self) -> &'a T { - * &self.value - * } - * } - * - * fn main() { - * let x = DerefExample { value: 'a' }; - * assert_eq!('a', *x); - * } - * ``` - */ -#[lang="deref"] -pub trait Deref { - /// The method called to dereference a value - fn deref<'a>(&'a self) -> &'a Result; -} - -/** - * - * The `DerefMut` trait is used to specify the functionality of dereferencing - * mutably like `*v = 1;` - * - * # Example - * - * A struct with a single field which is modifiable via dereferencing the - * struct. - * - * ``` - * struct DerefMutExample { - * value: T - * } - * - * impl Deref for DerefMutExample { - * fn deref<'a>(&'a self) -> &'a T { - * &self.value - * } - * } - * - * impl DerefMut for DerefMutExample { - * fn deref_mut<'a>(&'a mut self) -> &'a mut T { - * &mut self.value - * } - * } - * - * fn main() { - * let mut x = DerefMutExample { value: 'a' }; - * *x = 'b'; - * assert_eq!('b', *x); - * } - * ``` - */ -#[lang="deref_mut"] -pub trait DerefMut: Deref { - /// The method called to mutably dereference a value - fn deref_mut<'a>(&'a mut self) -> &'a mut Result; -} - -#[cfg(test)] -mod bench { - extern crate test; - use self::test::Bencher; - use ops::Drop; - - // Overhead of dtors - - struct HasDtor { - x: int - } - - impl Drop for HasDtor { - fn drop(&mut self) { - } - } - - #[bench] - fn alloc_obj_with_dtor(b: &mut Bencher) { - b.iter(|| { - HasDtor { x : 10 }; - }) - } -} -- cgit 1.4.1-3-g733a5 From 2ad98fbb27edcc1170fde800219a107faac4ae44 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:26:12 -0700 Subject: core: Inherit the ty module --- src/libcore/lib.rs | 1 + src/libcore/ty.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/lib.rs | 3 +-- src/libstd/ty.rs | 71 ------------------------------------------------------ 4 files changed, 73 insertions(+), 73 deletions(-) create mode 100644 src/libcore/ty.rs delete mode 100644 src/libstd/ty.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 42df97040f1..dd6b9e20d7a 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -32,3 +32,4 @@ pub mod ptr; pub mod kinds; pub mod ops; +pub mod ty; diff --git a/src/libcore/ty.rs b/src/libcore/ty.rs new file mode 100644 index 00000000000..0c9f0b02fdf --- /dev/null +++ b/src/libcore/ty.rs @@ -0,0 +1,71 @@ +// Copyright 2012-2013 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. + +//! Types dealing with unsafe actions. + +use cast; +use kinds::marker; + +/// Unsafe type that wraps a type T and indicates unsafe interior operations on the +/// wrapped type. Types with an `Unsafe` field are considered to have an *unsafe +/// interior*. The Unsafe type is the only legal way to obtain aliasable data that is +/// considered mutable. In general, transmuting an &T type into an &mut T is considered +/// undefined behavior. +/// +/// Although it is possible to put an Unsafe into static item, it is not permitted to +/// take the address of the static item if the item is not declared as mutable. This rule +/// exists because immutable static items are stored in read-only memory, and thus any +/// attempt to mutate their interior can cause segfaults. Immutable static items containing +/// Unsafe instances are still useful as read-only initializers, however, so we do not +/// forbid them altogether. +/// +/// Types like `Cell` and `RefCell` use this type to wrap their internal data. +/// +/// Unsafe doesn't opt-out from any kind, instead, types with an `Unsafe` interior +/// are expected to opt-out from kinds themselves. +/// +/// # Example: +/// +/// ```rust +/// use std::ty::Unsafe; +/// use std::kinds::marker; +/// +/// struct NotThreadSafe { +/// value: Unsafe, +/// marker1: marker::NoShare +/// } +/// ``` +/// +/// **NOTE:** Unsafe fields are public to allow static initializers. It is not recommended +/// to access its fields directly, `get` should be used instead. +#[lang="unsafe"] +pub struct Unsafe { + /// Wrapped value + pub value: T, + + /// Invariance marker + pub marker1: marker::InvariantType +} + +impl Unsafe { + + /// Static constructor + pub fn new(value: T) -> Unsafe { + Unsafe{value: value, marker1: marker::InvariantType} + } + + /// Gets a mutable pointer to the wrapped value + #[inline] + pub unsafe fn get(&self) -> *mut T { cast::transmute_mut_unsafe(&self.value) } + + /// Unwraps the value + #[inline] + pub unsafe fn unwrap(self) -> T { self.value } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 0ef623a558f..eada05bf487 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -135,6 +135,7 @@ extern crate core; #[cfg(not(test))] pub use kinds = core::kinds; #[cfg(not(test))] pub use ops = core::ops; +#[cfg(not(test))] pub use ty = core::ty; pub use core::cast; pub use core::intrinsics; @@ -196,7 +197,6 @@ pub mod strbuf; pub mod ascii; -pub mod owned; mod managed; mod reference; pub mod rc; @@ -206,7 +206,6 @@ pub mod gc; /* Core language traits */ #[cfg(not(test))] pub mod cmp; -#[cfg(not(test))] pub mod ty; #[cfg(not(test))] pub mod owned; diff --git a/src/libstd/ty.rs b/src/libstd/ty.rs deleted file mode 100644 index 0c9f0b02fdf..00000000000 --- a/src/libstd/ty.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2012-2013 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. - -//! Types dealing with unsafe actions. - -use cast; -use kinds::marker; - -/// Unsafe type that wraps a type T and indicates unsafe interior operations on the -/// wrapped type. Types with an `Unsafe` field are considered to have an *unsafe -/// interior*. The Unsafe type is the only legal way to obtain aliasable data that is -/// considered mutable. In general, transmuting an &T type into an &mut T is considered -/// undefined behavior. -/// -/// Although it is possible to put an Unsafe into static item, it is not permitted to -/// take the address of the static item if the item is not declared as mutable. This rule -/// exists because immutable static items are stored in read-only memory, and thus any -/// attempt to mutate their interior can cause segfaults. Immutable static items containing -/// Unsafe instances are still useful as read-only initializers, however, so we do not -/// forbid them altogether. -/// -/// Types like `Cell` and `RefCell` use this type to wrap their internal data. -/// -/// Unsafe doesn't opt-out from any kind, instead, types with an `Unsafe` interior -/// are expected to opt-out from kinds themselves. -/// -/// # Example: -/// -/// ```rust -/// use std::ty::Unsafe; -/// use std::kinds::marker; -/// -/// struct NotThreadSafe { -/// value: Unsafe, -/// marker1: marker::NoShare -/// } -/// ``` -/// -/// **NOTE:** Unsafe fields are public to allow static initializers. It is not recommended -/// to access its fields directly, `get` should be used instead. -#[lang="unsafe"] -pub struct Unsafe { - /// Wrapped value - pub value: T, - - /// Invariance marker - pub marker1: marker::InvariantType -} - -impl Unsafe { - - /// Static constructor - pub fn new(value: T) -> Unsafe { - Unsafe{value: value, marker1: marker::InvariantType} - } - - /// Gets a mutable pointer to the wrapped value - #[inline] - pub unsafe fn get(&self) -> *mut T { cast::transmute_mut_unsafe(&self.value) } - - /// Unwraps the value - #[inline] - pub unsafe fn unwrap(self) -> T { self.value } -} -- cgit 1.4.1-3-g733a5 From d9708539afa16bf233332fee846cc9c6d7344517 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:27:26 -0700 Subject: core: Inherit the container module --- src/libcore/container.rs | 108 +++++++++++++++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 1 + src/libstd/container.rs | 108 ----------------------------------------------- src/libstd/lib.rs | 2 +- 4 files changed, 110 insertions(+), 109 deletions(-) create mode 100644 src/libcore/container.rs delete mode 100644 src/libstd/container.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/container.rs b/src/libcore/container.rs new file mode 100644 index 00000000000..e8ee3792dcf --- /dev/null +++ b/src/libcore/container.rs @@ -0,0 +1,108 @@ +// Copyright 2013 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. + +//! Traits for generic containers (including `Map` and `Set`) + +use option::Option; + +/// A trait to represent the abstract idea of a container. The only concrete +/// knowledge known is the number of elements contained within. +pub trait Container { + /// Return the number of elements in the container + fn len(&self) -> uint; + + /// Return true if the container contains no elements + #[inline] + fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +/// A trait to represent mutable containers +pub trait Mutable: Container { + /// Clear the container, removing all values. + fn clear(&mut self); +} + +/// A map is a key-value store where values may be looked up by their keys. This +/// trait provides basic operations to operate on these stores. +pub trait Map: Container { + /// Return a reference to the value corresponding to the key + fn find<'a>(&'a self, key: &K) -> Option<&'a V>; + + /// Return true if the map contains a value for the specified key + #[inline] + fn contains_key(&self, key: &K) -> bool { + self.find(key).is_some() + } +} + +/// This trait provides basic operations to modify the contents of a map. +pub trait MutableMap: Map + Mutable { + /// Insert a key-value pair into the map. An existing value for a + /// key is replaced by the new value. Return true if the key did + /// not already exist in the map. + #[inline] + fn insert(&mut self, key: K, value: V) -> bool { + self.swap(key, value).is_none() + } + + /// Remove a key-value pair from the map. Return true if the key + /// was present in the map, otherwise false. + #[inline] + fn remove(&mut self, key: &K) -> bool { + self.pop(key).is_some() + } + + /// Insert a key-value pair from the map. If the key already had a value + /// present in the map, that value is returned. Otherwise None is returned. + fn swap(&mut self, k: K, v: V) -> Option; + + /// Removes a key from the map, returning the value at the key if the key + /// was previously in the map. + fn pop(&mut self, k: &K) -> Option; + + /// Return a mutable reference to the value corresponding to the key + fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V>; +} + +/// A set is a group of objects which are each distinct from one another. This +/// trait represents actions which can be performed on sets to iterate over +/// them. +pub trait Set: Container { + /// Return true if the set contains a value + fn contains(&self, value: &T) -> bool; + + /// Return true if the set has no elements in common with `other`. + /// This is equivalent to checking for an empty intersection. + fn is_disjoint(&self, other: &Self) -> bool; + + /// Return true if the set is a subset of another + fn is_subset(&self, other: &Self) -> bool; + + /// Return true if the set is a superset of another + fn is_superset(&self, other: &Self) -> bool { + other.is_subset(self) + } + + // FIXME #8154: Add difference, sym. difference, intersection and union iterators +} + +/// This trait represents actions which can be performed on sets to mutate +/// them. +pub trait MutableSet: Set + Mutable { + /// Add a value to the set. Return true if the value was not already + /// present in the set. + fn insert(&mut self, value: T) -> bool; + + /// Remove a value from the set. Return true if the value was + /// present in the set. + fn remove(&mut self, value: &T) -> bool; +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index dd6b9e20d7a..1f94b41b9bb 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -33,3 +33,4 @@ pub mod ptr; pub mod kinds; pub mod ops; pub mod ty; +pub mod container; diff --git a/src/libstd/container.rs b/src/libstd/container.rs deleted file mode 100644 index e8ee3792dcf..00000000000 --- a/src/libstd/container.rs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2013 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. - -//! Traits for generic containers (including `Map` and `Set`) - -use option::Option; - -/// A trait to represent the abstract idea of a container. The only concrete -/// knowledge known is the number of elements contained within. -pub trait Container { - /// Return the number of elements in the container - fn len(&self) -> uint; - - /// Return true if the container contains no elements - #[inline] - fn is_empty(&self) -> bool { - self.len() == 0 - } -} - -/// A trait to represent mutable containers -pub trait Mutable: Container { - /// Clear the container, removing all values. - fn clear(&mut self); -} - -/// A map is a key-value store where values may be looked up by their keys. This -/// trait provides basic operations to operate on these stores. -pub trait Map: Container { - /// Return a reference to the value corresponding to the key - fn find<'a>(&'a self, key: &K) -> Option<&'a V>; - - /// Return true if the map contains a value for the specified key - #[inline] - fn contains_key(&self, key: &K) -> bool { - self.find(key).is_some() - } -} - -/// This trait provides basic operations to modify the contents of a map. -pub trait MutableMap: Map + Mutable { - /// Insert a key-value pair into the map. An existing value for a - /// key is replaced by the new value. Return true if the key did - /// not already exist in the map. - #[inline] - fn insert(&mut self, key: K, value: V) -> bool { - self.swap(key, value).is_none() - } - - /// Remove a key-value pair from the map. Return true if the key - /// was present in the map, otherwise false. - #[inline] - fn remove(&mut self, key: &K) -> bool { - self.pop(key).is_some() - } - - /// Insert a key-value pair from the map. If the key already had a value - /// present in the map, that value is returned. Otherwise None is returned. - fn swap(&mut self, k: K, v: V) -> Option; - - /// Removes a key from the map, returning the value at the key if the key - /// was previously in the map. - fn pop(&mut self, k: &K) -> Option; - - /// Return a mutable reference to the value corresponding to the key - fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V>; -} - -/// A set is a group of objects which are each distinct from one another. This -/// trait represents actions which can be performed on sets to iterate over -/// them. -pub trait Set: Container { - /// Return true if the set contains a value - fn contains(&self, value: &T) -> bool; - - /// Return true if the set has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - fn is_disjoint(&self, other: &Self) -> bool; - - /// Return true if the set is a subset of another - fn is_subset(&self, other: &Self) -> bool; - - /// Return true if the set is a superset of another - fn is_superset(&self, other: &Self) -> bool { - other.is_subset(self) - } - - // FIXME #8154: Add difference, sym. difference, intersection and union iterators -} - -/// This trait represents actions which can be performed on sets to mutate -/// them. -pub trait MutableSet: Set + Mutable { - /// Add a value to the set. Return true if the value was not already - /// present in the set. - fn insert(&mut self, value: T) -> bool; - - /// Remove a value from the set. Return true if the value was - /// present in the set. - fn remove(&mut self, value: &T) -> bool; -} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index eada05bf487..44684ba97c2 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -138,6 +138,7 @@ extern crate core; #[cfg(not(test))] pub use ty = core::ty; pub use core::cast; +pub use core::container; pub use core::intrinsics; pub use core::mem; pub use core::ptr; @@ -217,7 +218,6 @@ pub mod iter; pub mod to_str; pub mod clone; pub mod hash; -pub mod container; pub mod default; pub mod any; -- cgit 1.4.1-3-g733a5 From 71924525458e508be139d76f48b34e64a5a9dca3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:33:08 -0700 Subject: core: Inherit the char module --- src/libcore/char.rs | 854 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 4 + src/libstd/char.rs | 845 --------------------------------------------------- src/libstd/lib.rs | 2 +- 4 files changed, 859 insertions(+), 846 deletions(-) create mode 100644 src/libcore/char.rs delete mode 100644 src/libstd/char.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/char.rs b/src/libcore/char.rs new file mode 100644 index 00000000000..7a52af82403 --- /dev/null +++ b/src/libcore/char.rs @@ -0,0 +1,854 @@ +// Copyright 2012-2013 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. + +//! Character manipulation (`char` type, Unicode Scalar Value) +//! +//! This module provides the `Char` trait, as well as its implementation +//! for the primitive `char` type, in order to allow basic character manipulation. +//! +//! A `char` actually represents a +//! *[Unicode Scalar Value](http://www.unicode.org/glossary/#unicode_scalar_value)*, +//! as it can contain any Unicode code point except high-surrogate and +//! low-surrogate code points. +//! +//! As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\] +//! (inclusive) are allowed. A `char` can always be safely cast to a `u32`; +//! however the converse is not always true due to the above range limits +//! and, as such, should be performed via the `from_u32` function.. + + +use cast::transmute; +use option::{None, Option, Some}; +use iter::{Iterator, range_step}; +use unicode::{derived_property, property, general_category, decompose, conversions}; + +#[cfg(test)] use str::Str; +#[cfg(test)] use strbuf::StrBuf; +#[cfg(test)] use slice::ImmutableVector; + +#[cfg(not(test))] use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering}; +#[cfg(not(test))] use default::Default; + +// UTF-8 ranges and tags for encoding characters +static TAG_CONT: uint = 128u; +static MAX_ONE_B: uint = 128u; +static TAG_TWO_B: uint = 192u; +static MAX_TWO_B: uint = 2048u; +static TAG_THREE_B: uint = 224u; +static MAX_THREE_B: uint = 65536u; +static TAG_FOUR_B: uint = 240u; + +/* + Lu Uppercase_Letter an uppercase letter + Ll Lowercase_Letter a lowercase letter + Lt Titlecase_Letter a digraphic character, with first part uppercase + Lm Modifier_Letter a modifier letter + Lo Other_Letter other letters, including syllables and ideographs + Mn Nonspacing_Mark a nonspacing combining mark (zero advance width) + Mc Spacing_Mark a spacing combining mark (positive advance width) + Me Enclosing_Mark an enclosing combining mark + Nd Decimal_Number a decimal digit + Nl Letter_Number a letterlike numeric character + No Other_Number a numeric character of other type + Pc Connector_Punctuation a connecting punctuation mark, like a tie + Pd Dash_Punctuation a dash or hyphen punctuation mark + Ps Open_Punctuation an opening punctuation mark (of a pair) + Pe Close_Punctuation a closing punctuation mark (of a pair) + Pi Initial_Punctuation an initial quotation mark + Pf Final_Punctuation a final quotation mark + Po Other_Punctuation a punctuation mark of other type + Sm Math_Symbol a symbol of primarily mathematical use + Sc Currency_Symbol a currency sign + Sk Modifier_Symbol a non-letterlike modifier symbol + So Other_Symbol a symbol of other type + Zs Space_Separator a space character (of various non-zero widths) + Zl Line_Separator U+2028 LINE SEPARATOR only + Zp Paragraph_Separator U+2029 PARAGRAPH SEPARATOR only + Cc Control a C0 or C1 control code + Cf Format a format control character + Cs Surrogate a surrogate code point + Co Private_Use a private-use character + Cn Unassigned a reserved unassigned code point or a noncharacter +*/ + +/// The highest valid code point +pub static MAX: char = '\U0010ffff'; + +/// Converts from `u32` to a `char` +#[inline] +pub fn from_u32(i: u32) -> Option { + // catch out-of-bounds and surrogates + if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) { + None + } else { + Some(unsafe { transmute(i) }) + } +} + +/// Returns whether the specified `char` is considered a Unicode alphabetic +/// code point +pub fn is_alphabetic(c: char) -> bool { derived_property::Alphabetic(c) } + +/// Returns whether the specified `char` 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. +pub fn is_XID_start(c: char) -> bool { derived_property::XID_Start(c) } + +/// 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. +pub fn is_XID_continue(c: char) -> bool { derived_property::XID_Continue(c) } + +/// +/// Indicates whether a `char` is in lower case +/// +/// This is defined according to the terms of the Unicode Derived Core Property 'Lowercase'. +/// +#[inline] +pub fn is_lowercase(c: char) -> bool { derived_property::Lowercase(c) } + +/// +/// Indicates whether a `char` is in upper case +/// +/// This is defined according to the terms of the Unicode Derived Core Property 'Uppercase'. +/// +#[inline] +pub fn is_uppercase(c: char) -> bool { derived_property::Uppercase(c) } + +/// +/// Indicates whether a `char` is whitespace +/// +/// Whitespace is defined in terms of the Unicode Property 'White_Space'. +/// +#[inline] +pub fn is_whitespace(c: char) -> bool { + // As an optimization ASCII whitespace characters are checked separately + c == ' ' + || ('\x09' <= c && c <= '\x0d') + || property::White_Space(c) +} + +/// +/// Indicates whether a `char` is alphanumeric +/// +/// Alphanumericness is defined in terms of the Unicode General Categories +/// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'. +/// +#[inline] +pub fn is_alphanumeric(c: char) -> bool { + derived_property::Alphabetic(c) + || general_category::Nd(c) + || general_category::Nl(c) + || general_category::No(c) +} + +/// +/// Indicates whether a `char` is a control code point +/// +/// Control code points are defined in terms of the Unicode General Category +/// 'Cc'. +/// +#[inline] +pub fn is_control(c: char) -> bool { general_category::Cc(c) } + +/// Indicates whether the `char` is numeric (Nd, Nl, or No) +#[inline] +pub fn is_digit(c: char) -> bool { + general_category::Nd(c) + || general_category::Nl(c) + || general_category::No(c) +} + +/// +/// Checks if a `char` parses as a numeric digit in the given radix +/// +/// Compared to `is_digit()`, 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. +/// +/// # Failure +/// +/// Fails if given a `radix` > 36. +/// +/// # Note +/// +/// This just wraps `to_digit()`. +/// +#[inline] +pub fn is_digit_radix(c: char, radix: uint) -> bool { + match to_digit(c, radix) { + Some(_) => true, + None => false, + } +} + +/// +/// Converts a `char` 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 `char` does not +/// refer to a digit in the given radix. +/// +/// # Failure +/// +/// Fails if given a `radix` outside the range `[0..36]`. +/// +#[inline] +pub fn to_digit(c: char, radix: uint) -> Option { + if radix > 36 { + fail!("to_digit: radix {} is too high (maximum 36)", radix); + } + let val = match c { + '0' .. '9' => c as uint - ('0' as uint), + 'a' .. 'z' => c as uint + 10u - ('a' as uint), + 'A' .. 'Z' => c as uint + 10u - ('A' as uint), + _ => return None, + }; + if val < radix { Some(val) } + else { None } +} + +/// Convert a char to its uppercase equivalent +/// +/// The case-folding performed is the common or simple mapping: +/// it maps one unicode codepoint (one char in Rust) to its uppercase equivalent according +/// to the Unicode database at ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt +/// The additional SpecialCasing.txt is not considered here, as it expands to multiple +/// codepoints in some cases. +/// +/// A full reference can be found here +/// http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992 +/// +/// # Return value +/// +/// Returns the char itself if no conversion was made +#[inline] +pub fn to_uppercase(c: char) -> char { + conversions::to_upper(c) +} + +/// Convert a char 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 the char itself if no conversion if possible +#[inline] +pub fn to_lowercase(c: char) -> char { + conversions::to_lower(c) +} + +/// +/// Converts a number to the character representing it +/// +/// # Return value +/// +/// Returns `Some(char)` if `num` represents one digit under `radix`, +/// using one character of `0-9` or `a-z`, or `None` if it doesn't. +/// +/// # Failure +/// +/// Fails if given an `radix` > 36. +/// +#[inline] +pub fn from_digit(num: uint, radix: uint) -> Option { + if radix > 36 { + fail!("from_digit: radix {} is to high (maximum 36)", num); + } + if num < radix { + unsafe { + if num < 10 { + Some(transmute(('0' as uint + num) as u32)) + } else { + Some(transmute(('a' as uint + num - 10u) as u32)) + } + } + } else { + None + } +} + +// Constants from Unicode 6.2.0 Section 3.12 Conjoining Jamo Behavior +static S_BASE: uint = 0xAC00; +static L_BASE: uint = 0x1100; +static V_BASE: uint = 0x1161; +static T_BASE: uint = 0x11A7; +static L_COUNT: uint = 19; +static V_COUNT: uint = 21; +static T_COUNT: uint = 28; +static N_COUNT: uint = (V_COUNT * T_COUNT); +static S_COUNT: uint = (L_COUNT * N_COUNT); + +// Decompose a precomposed Hangul syllable +fn decompose_hangul(s: char, f: |char|) { + let si = s as uint - S_BASE; + + let li = si / N_COUNT; + unsafe { + f(transmute((L_BASE + li) as u32)); + + let vi = (si % N_COUNT) / T_COUNT; + f(transmute((V_BASE + vi) as u32)); + + let ti = si % T_COUNT; + if ti > 0 { + f(transmute((T_BASE + ti) as u32)); + } + } +} + +/// Returns the canonical decomposition of a character +pub fn decompose_canonical(c: char, f: |char|) { + if (c as uint) < S_BASE || (c as uint) >= (S_BASE + S_COUNT) { + decompose::canonical(c, f); + } else { + decompose_hangul(c, f); + } +} + +/// Returns the compatibility decomposition of a character +pub fn decompose_compatible(c: char, f: |char|) { + if (c as uint) < S_BASE || (c as uint) >= (S_BASE + S_COUNT) { + decompose::compatibility(c, f); + } else { + decompose_hangul(c, f); + } +} + +/// +/// Returns the hexadecimal Unicode escape of a `char` +/// +/// The rules are as follows: +/// +/// - chars in [0,0xff] get 2-digit escapes: `\\xNN` +/// - chars in [0x100,0xffff] get 4-digit escapes: `\\uNNNN` +/// - chars above 0x10000 get 8-digit escapes: `\\UNNNNNNNN` +/// +pub fn escape_unicode(c: char, f: |char|) { + // avoid calling str::to_str_radix because we don't really need to allocate + // here. + f('\\'); + let pad = match () { + _ if c <= '\xff' => { f('x'); 2 } + _ if c <= '\uffff' => { f('u'); 4 } + _ => { f('U'); 8 } + }; + for offset in range_step::(4 * (pad - 1), -1, -4) { + unsafe { + match ((c as i32) >> offset) & 0xf { + i @ 0 .. 9 => { f(transmute('0' as i32 + i)); } + i => { f(transmute('a' as i32 + (i - 10))); } + } + } + } +} + +/// +/// Returns a 'default' ASCII and C++11-like literal escape of a `char` +/// +/// 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`. +/// +pub fn escape_default(c: char, f: |char|) { + match c { + '\t' => { f('\\'); f('t'); } + '\r' => { f('\\'); f('r'); } + '\n' => { f('\\'); f('n'); } + '\\' => { f('\\'); f('\\'); } + '\'' => { f('\\'); f('\''); } + '"' => { f('\\'); f('"'); } + '\x20' .. '\x7e' => { f(c); } + _ => c.escape_unicode(f), + } +} + +/// Returns the amount of bytes this `char` would need if encoded in UTF-8 +pub fn len_utf8_bytes(c: char) -> uint { + static MAX_ONE_B: uint = 128u; + static MAX_TWO_B: uint = 2048u; + static MAX_THREE_B: uint = 65536u; + static MAX_FOUR_B: uint = 2097152u; + + let code = c as uint; + match () { + _ if code < MAX_ONE_B => 1u, + _ if code < MAX_TWO_B => 2u, + _ if code < MAX_THREE_B => 3u, + _ if code < MAX_FOUR_B => 4u, + _ => fail!("invalid character!"), + } +} + +/// Useful functions for Unicode characters. +pub trait Char { + /// Returns whether the specified character is considered a Unicode + /// alphabetic code point. + fn is_alphabetic(&self) -> bool; + + /// 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. + fn is_XID_start(&self) -> bool; + + /// 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. + fn is_XID_continue(&self) -> bool; + + + /// Indicates whether a character is in lowercase. + /// + /// This is defined according to the terms of the Unicode Derived Core + /// Property `Lowercase`. + fn is_lowercase(&self) -> bool; + + /// Indicates whether a character is in uppercase. + /// + /// This is defined according to the terms of the Unicode Derived Core + /// Property `Uppercase`. + fn is_uppercase(&self) -> bool; + + /// Indicates whether a character is whitespace. + /// + /// Whitespace is defined in terms of the Unicode Property `White_Space`. + fn is_whitespace(&self) -> bool; + + /// 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'. + fn is_alphanumeric(&self) -> bool; + + /// Indicates whether a character is a control code point. + /// + /// Control code points are defined in terms of the Unicode General + /// Category `Cc`. + fn is_control(&self) -> bool; + + /// Indicates whether the character is numeric (Nd, Nl, or No). + fn is_digit(&self) -> bool; + + /// Checks if a `char` parses as a numeric digit in the given radix. + /// + /// Compared to `is_digit()`, 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. + /// + /// # Failure + /// + /// Fails if given a radix > 36. + fn is_digit_radix(&self, radix: uint) -> bool; + + /// 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. + /// + /// # Failure + /// + /// Fails if given a radix outside the range [0..36]. + fn to_digit(&self, radix: uint) -> Option; + + /// 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 the lowercase equivalent of the character, or the character + /// itself if no conversion is possible. + fn to_lowercase(&self) -> char; + + /// Converts a character to its uppercase equivalent. + /// + /// The case-folding performed is the common or simple mapping: it maps + /// one unicode codepoint (one character in Rust) to its uppercase + /// equivalent according to the Unicode database [1]. The additional + /// `SpecialCasing.txt` is not considered here, as it expands to multiple + /// codepoints in some cases. + /// + /// A full reference can be found here [2]. + /// + /// # Return value + /// + /// Returns the uppercase equivalent of the character, or the character + /// itself if no conversion was made. + /// + /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt + /// + /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992 + fn to_uppercase(&self) -> char; + + /// Converts a number to the character representing it. + /// + /// # Return value + /// + /// Returns `Some(char)` if `num` represents one digit under `radix`, + /// using one character of `0-9` or `a-z`, or `None` if it doesn't. + /// + /// # Failure + /// + /// Fails if given a radix > 36. + fn from_digit(num: uint, radix: uint) -> Option; + + /// Returns the hexadecimal Unicode escape of a character. + /// + /// The rules are as follows: + /// + /// * Characters in [0,0xff] get 2-digit escapes: `\\xNN` + /// * Characters in [0x100,0xffff] get 4-digit escapes: `\\uNNNN`. + /// * Characters above 0x10000 get 8-digit escapes: `\\UNNNNNNNN`. + fn escape_unicode(&self, f: |char|); + + /// Returns a 'default' ASCII and C++11-like literal escape of a + /// character. + /// + /// 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`. + fn escape_default(&self, f: |char|); + + /// Returns the amount of bytes this character would need if encoded in + /// UTF-8. + fn len_utf8_bytes(&self) -> uint; + + /// Encodes this character as UTF-8 into the provided byte buffer. + /// + /// The buffer must be at least 4 bytes long or a runtime failure may + /// occur. + /// + /// This will then return the number of bytes written to the slice. + fn encode_utf8(&self, dst: &mut [u8]) -> uint; + + /// Encodes this character as UTF-16 into the provided `u16` buffer. + /// + /// The buffer must be at least 2 elements long or a runtime failure may + /// occur. + /// + /// This will then return the number of `u16`s written to the slice. + fn encode_utf16(&self, dst: &mut [u16]) -> uint; +} + +impl Char for char { + fn is_alphabetic(&self) -> bool { is_alphabetic(*self) } + + fn is_XID_start(&self) -> bool { is_XID_start(*self) } + + fn is_XID_continue(&self) -> bool { is_XID_continue(*self) } + + fn is_lowercase(&self) -> bool { is_lowercase(*self) } + + fn is_uppercase(&self) -> bool { is_uppercase(*self) } + + fn is_whitespace(&self) -> bool { is_whitespace(*self) } + + fn is_alphanumeric(&self) -> bool { is_alphanumeric(*self) } + + fn is_control(&self) -> bool { is_control(*self) } + + fn is_digit(&self) -> bool { is_digit(*self) } + + fn is_digit_radix(&self, radix: uint) -> bool { is_digit_radix(*self, radix) } + + fn to_digit(&self, radix: uint) -> Option { to_digit(*self, radix) } + + fn to_lowercase(&self) -> char { to_lowercase(*self) } + + fn to_uppercase(&self) -> char { to_uppercase(*self) } + + fn from_digit(num: uint, radix: uint) -> Option { from_digit(num, radix) } + + fn escape_unicode(&self, f: |char|) { escape_unicode(*self, f) } + + fn escape_default(&self, f: |char|) { escape_default(*self, f) } + + fn len_utf8_bytes(&self) -> uint { len_utf8_bytes(*self) } + + fn encode_utf8(&self, dst: &mut [u8]) -> uint { + let code = *self as uint; + if code < MAX_ONE_B { + dst[0] = code as u8; + return 1; + } else if code < MAX_TWO_B { + dst[0] = (code >> 6u & 31u | TAG_TWO_B) as u8; + dst[1] = (code & 63u | TAG_CONT) as u8; + return 2; + } else if code < MAX_THREE_B { + dst[0] = (code >> 12u & 15u | TAG_THREE_B) as u8; + dst[1] = (code >> 6u & 63u | TAG_CONT) as u8; + dst[2] = (code & 63u | TAG_CONT) as u8; + return 3; + } else { + dst[0] = (code >> 18u & 7u | TAG_FOUR_B) as u8; + dst[1] = (code >> 12u & 63u | TAG_CONT) as u8; + dst[2] = (code >> 6u & 63u | TAG_CONT) as u8; + dst[3] = (code & 63u | TAG_CONT) as u8; + return 4; + } + } + + fn encode_utf16(&self, dst: &mut [u16]) -> uint { + let mut ch = *self as uint; + if (ch & 0xFFFF_u) == ch { + // The BMP falls through (assuming non-surrogate, as it + // should) + assert!(ch <= 0xD7FF_u || ch >= 0xE000_u); + dst[0] = ch as u16; + 1 + } else { + // Supplementary planes break into surrogates. + assert!(ch >= 0x1_0000_u && ch <= 0x10_FFFF_u); + ch -= 0x1_0000_u; + dst[0] = 0xD800_u16 | ((ch >> 10) as u16); + dst[1] = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); + 2 + } + } +} + +#[cfg(not(test))] +impl Eq for char { + #[inline] + fn eq(&self, other: &char) -> bool { (*self) == (*other) } +} + +#[cfg(not(test))] +impl TotalEq for char {} + +#[cfg(not(test))] +impl Ord for char { + #[inline] + fn lt(&self, other: &char) -> bool { *self < *other } +} + +#[cfg(not(test))] +impl TotalOrd for char { + fn cmp(&self, other: &char) -> Ordering { + (*self as u32).cmp(&(*other as u32)) + } +} + +#[cfg(not(test))] +impl Default for char { + #[inline] + fn default() -> char { '\x00' } +} + +#[test] +fn test_is_lowercase() { + assert!('a'.is_lowercase()); + assert!('ö'.is_lowercase()); + assert!('ß'.is_lowercase()); + assert!(!'Ü'.is_lowercase()); + assert!(!'P'.is_lowercase()); +} + +#[test] +fn test_is_uppercase() { + assert!(!'h'.is_uppercase()); + assert!(!'ä'.is_uppercase()); + assert!(!'ß'.is_uppercase()); + assert!('Ö'.is_uppercase()); + assert!('T'.is_uppercase()); +} + +#[test] +fn test_is_whitespace() { + assert!(' '.is_whitespace()); + assert!('\u2007'.is_whitespace()); + assert!('\t'.is_whitespace()); + assert!('\n'.is_whitespace()); + assert!(!'a'.is_whitespace()); + assert!(!'_'.is_whitespace()); + assert!(!'\u0000'.is_whitespace()); +} + +#[test] +fn test_to_digit() { + assert_eq!('0'.to_digit(10u), Some(0u)); + assert_eq!('1'.to_digit(2u), Some(1u)); + assert_eq!('2'.to_digit(3u), Some(2u)); + assert_eq!('9'.to_digit(10u), Some(9u)); + assert_eq!('a'.to_digit(16u), Some(10u)); + assert_eq!('A'.to_digit(16u), Some(10u)); + assert_eq!('b'.to_digit(16u), Some(11u)); + assert_eq!('B'.to_digit(16u), Some(11u)); + assert_eq!('z'.to_digit(36u), Some(35u)); + assert_eq!('Z'.to_digit(36u), Some(35u)); + assert_eq!(' '.to_digit(10u), None); + assert_eq!('$'.to_digit(36u), None); +} + +#[test] +fn test_to_lowercase() { + assert_eq!('A'.to_lowercase(), 'a'); + assert_eq!('Ö'.to_lowercase(), 'ö'); + assert_eq!('ß'.to_lowercase(), 'ß'); + assert_eq!('Ü'.to_lowercase(), 'ü'); + assert_eq!('💩'.to_lowercase(), '💩'); + assert_eq!('Σ'.to_lowercase(), 'σ'); + assert_eq!('Τ'.to_lowercase(), 'τ'); + assert_eq!('Ι'.to_lowercase(), 'ι'); + assert_eq!('Γ'.to_lowercase(), 'γ'); + assert_eq!('Μ'.to_lowercase(), 'μ'); + assert_eq!('Α'.to_lowercase(), 'α'); + assert_eq!('Σ'.to_lowercase(), 'σ'); +} + +#[test] +fn test_to_uppercase() { + assert_eq!('a'.to_uppercase(), 'A'); + assert_eq!('ö'.to_uppercase(), 'Ö'); + assert_eq!('ß'.to_uppercase(), 'ß'); // not ẞ: Latin capital letter sharp s + assert_eq!('ü'.to_uppercase(), 'Ü'); + assert_eq!('💩'.to_uppercase(), '💩'); + + assert_eq!('σ'.to_uppercase(), 'Σ'); + assert_eq!('τ'.to_uppercase(), 'Τ'); + assert_eq!('ι'.to_uppercase(), 'Ι'); + assert_eq!('γ'.to_uppercase(), 'Γ'); + assert_eq!('μ'.to_uppercase(), 'Μ'); + assert_eq!('α'.to_uppercase(), 'Α'); + assert_eq!('ς'.to_uppercase(), 'Σ'); +} + +#[test] +fn test_is_control() { + assert!('\u0000'.is_control()); + assert!('\u0003'.is_control()); + assert!('\u0006'.is_control()); + assert!('\u0009'.is_control()); + assert!('\u007f'.is_control()); + assert!('\u0092'.is_control()); + assert!(!'\u0020'.is_control()); + assert!(!'\u0055'.is_control()); + assert!(!'\u0068'.is_control()); +} + +#[test] +fn test_is_digit() { + assert!('2'.is_digit()); + assert!('7'.is_digit()); + assert!(!'c'.is_digit()); + assert!(!'i'.is_digit()); + assert!(!'z'.is_digit()); + assert!(!'Q'.is_digit()); +} + +#[test] +fn test_escape_default() { + fn string(c: char) -> ~str { + let mut result = StrBuf::new(); + escape_default(c, |c| { result.push_char(c); }); + return result.into_owned(); + } + assert_eq!(string('\n'), "\\n".to_owned()); + assert_eq!(string('\r'), "\\r".to_owned()); + assert_eq!(string('\''), "\\'".to_owned()); + assert_eq!(string('"'), "\\\"".to_owned()); + assert_eq!(string(' '), " ".to_owned()); + assert_eq!(string('a'), "a".to_owned()); + assert_eq!(string('~'), "~".to_owned()); + assert_eq!(string('\x00'), "\\x00".to_owned()); + assert_eq!(string('\x1f'), "\\x1f".to_owned()); + assert_eq!(string('\x7f'), "\\x7f".to_owned()); + assert_eq!(string('\xff'), "\\xff".to_owned()); + assert_eq!(string('\u011b'), "\\u011b".to_owned()); + assert_eq!(string('\U0001d4b6'), "\\U0001d4b6".to_owned()); +} + +#[test] +fn test_escape_unicode() { + fn string(c: char) -> ~str { + let mut result = StrBuf::new(); + escape_unicode(c, |c| { result.push_char(c); }); + return result.into_owned(); + } + assert_eq!(string('\x00'), "\\x00".to_owned()); + assert_eq!(string('\n'), "\\x0a".to_owned()); + assert_eq!(string(' '), "\\x20".to_owned()); + assert_eq!(string('a'), "\\x61".to_owned()); + assert_eq!(string('\u011b'), "\\u011b".to_owned()); + assert_eq!(string('\U0001d4b6'), "\\U0001d4b6".to_owned()); +} + +#[test] +fn test_to_str() { + use to_str::ToStr; + let s = 't'.to_str(); + assert_eq!(s, "t".to_owned()); +} + +#[test] +fn test_encode_utf8() { + fn check(input: char, expect: &[u8]) { + let mut buf = [0u8, ..4]; + let n = input.encode_utf8(buf /* as mut slice! */); + assert_eq!(buf.slice_to(n), expect); + } + + check('x', [0x78]); + check('\u00e9', [0xc3, 0xa9]); + check('\ua66e', [0xea, 0x99, 0xae]); + check('\U0001f4a9', [0xf0, 0x9f, 0x92, 0xa9]); +} + +#[test] +fn test_encode_utf16() { + fn check(input: char, expect: &[u16]) { + let mut buf = [0u16, ..2]; + let n = input.encode_utf16(buf /* as mut slice! */); + assert_eq!(buf.slice_to(n), expect); + } + + check('x', [0x0078]); + check('\u00e9', [0x00e9]); + check('\ua66e', [0xa66e]); + check('\U0001f4a9', [0xd83d, 0xdca9]); +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 1f94b41b9bb..dd64148aa2b 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -34,3 +34,7 @@ pub mod kinds; pub mod ops; pub mod ty; pub mod container; + +/* Core types and methods on primitives */ + +pub mod char; diff --git a/src/libstd/char.rs b/src/libstd/char.rs deleted file mode 100644 index 228db221cfc..00000000000 --- a/src/libstd/char.rs +++ /dev/null @@ -1,845 +0,0 @@ -// Copyright 2012-2013 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. - -//! Character manipulation (`char` type, Unicode Scalar Value) -//! -//! This module provides the `Char` trait, as well as its implementation -//! for the primitive `char` type, in order to allow basic character manipulation. -//! -//! A `char` actually represents a -//! *[Unicode Scalar Value](http://www.unicode.org/glossary/#unicode_scalar_value)*, -//! as it can contain any Unicode code point except high-surrogate and -//! low-surrogate code points. -//! -//! As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\] -//! (inclusive) are allowed. A `char` can always be safely cast to a `u32`; -//! however the converse is not always true due to the above range limits -//! and, as such, should be performed via the `from_u32` function.. - - -use cast::transmute; -use option::{None, Option, Some}; -use iter::{Iterator, range_step}; -use str::StrSlice; -use unicode::{derived_property, property, general_category, decompose, conversions}; - -#[cfg(test)] use str::Str; -#[cfg(test)] use strbuf::StrBuf; -#[cfg(test)] use slice::ImmutableVector; - -#[cfg(not(test))] use cmp::{Eq, Ord}; -#[cfg(not(test))] use default::Default; - -// UTF-8 ranges and tags for encoding characters -static TAG_CONT: uint = 128u; -static MAX_ONE_B: uint = 128u; -static TAG_TWO_B: uint = 192u; -static MAX_TWO_B: uint = 2048u; -static TAG_THREE_B: uint = 224u; -static MAX_THREE_B: uint = 65536u; -static TAG_FOUR_B: uint = 240u; - -/* - Lu Uppercase_Letter an uppercase letter - Ll Lowercase_Letter a lowercase letter - Lt Titlecase_Letter a digraphic character, with first part uppercase - Lm Modifier_Letter a modifier letter - Lo Other_Letter other letters, including syllables and ideographs - Mn Nonspacing_Mark a nonspacing combining mark (zero advance width) - Mc Spacing_Mark a spacing combining mark (positive advance width) - Me Enclosing_Mark an enclosing combining mark - Nd Decimal_Number a decimal digit - Nl Letter_Number a letterlike numeric character - No Other_Number a numeric character of other type - Pc Connector_Punctuation a connecting punctuation mark, like a tie - Pd Dash_Punctuation a dash or hyphen punctuation mark - Ps Open_Punctuation an opening punctuation mark (of a pair) - Pe Close_Punctuation a closing punctuation mark (of a pair) - Pi Initial_Punctuation an initial quotation mark - Pf Final_Punctuation a final quotation mark - Po Other_Punctuation a punctuation mark of other type - Sm Math_Symbol a symbol of primarily mathematical use - Sc Currency_Symbol a currency sign - Sk Modifier_Symbol a non-letterlike modifier symbol - So Other_Symbol a symbol of other type - Zs Space_Separator a space character (of various non-zero widths) - Zl Line_Separator U+2028 LINE SEPARATOR only - Zp Paragraph_Separator U+2029 PARAGRAPH SEPARATOR only - Cc Control a C0 or C1 control code - Cf Format a format control character - Cs Surrogate a surrogate code point - Co Private_Use a private-use character - Cn Unassigned a reserved unassigned code point or a noncharacter -*/ - -/// The highest valid code point -pub static MAX: char = '\U0010ffff'; - -/// Converts from `u32` to a `char` -#[inline] -pub fn from_u32(i: u32) -> Option { - // catch out-of-bounds and surrogates - if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) { - None - } else { - Some(unsafe { transmute(i) }) - } -} - -/// Returns whether the specified `char` is considered a Unicode alphabetic -/// code point -pub fn is_alphabetic(c: char) -> bool { derived_property::Alphabetic(c) } - -/// Returns whether the specified `char` 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. -pub fn is_XID_start(c: char) -> bool { derived_property::XID_Start(c) } - -/// 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. -pub fn is_XID_continue(c: char) -> bool { derived_property::XID_Continue(c) } - -/// -/// Indicates whether a `char` is in lower case -/// -/// This is defined according to the terms of the Unicode Derived Core Property 'Lowercase'. -/// -#[inline] -pub fn is_lowercase(c: char) -> bool { derived_property::Lowercase(c) } - -/// -/// Indicates whether a `char` is in upper case -/// -/// This is defined according to the terms of the Unicode Derived Core Property 'Uppercase'. -/// -#[inline] -pub fn is_uppercase(c: char) -> bool { derived_property::Uppercase(c) } - -/// -/// Indicates whether a `char` is whitespace -/// -/// Whitespace is defined in terms of the Unicode Property 'White_Space'. -/// -#[inline] -pub fn is_whitespace(c: char) -> bool { - // As an optimization ASCII whitespace characters are checked separately - c == ' ' - || ('\x09' <= c && c <= '\x0d') - || property::White_Space(c) -} - -/// -/// Indicates whether a `char` is alphanumeric -/// -/// Alphanumericness is defined in terms of the Unicode General Categories -/// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'. -/// -#[inline] -pub fn is_alphanumeric(c: char) -> bool { - derived_property::Alphabetic(c) - || general_category::Nd(c) - || general_category::Nl(c) - || general_category::No(c) -} - -/// -/// Indicates whether a `char` is a control code point -/// -/// Control code points are defined in terms of the Unicode General Category -/// 'Cc'. -/// -#[inline] -pub fn is_control(c: char) -> bool { general_category::Cc(c) } - -/// Indicates whether the `char` is numeric (Nd, Nl, or No) -#[inline] -pub fn is_digit(c: char) -> bool { - general_category::Nd(c) - || general_category::Nl(c) - || general_category::No(c) -} - -/// -/// Checks if a `char` parses as a numeric digit in the given radix -/// -/// Compared to `is_digit()`, 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. -/// -/// # Failure -/// -/// Fails if given a `radix` > 36. -/// -/// # Note -/// -/// This just wraps `to_digit()`. -/// -#[inline] -pub fn is_digit_radix(c: char, radix: uint) -> bool { - match to_digit(c, radix) { - Some(_) => true, - None => false, - } -} - -/// -/// Converts a `char` 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 `char` does not -/// refer to a digit in the given radix. -/// -/// # Failure -/// -/// Fails if given a `radix` outside the range `[0..36]`. -/// -#[inline] -pub fn to_digit(c: char, radix: uint) -> Option { - if radix > 36 { - fail!("to_digit: radix {} is too high (maximum 36)", radix); - } - let val = match c { - '0' .. '9' => c as uint - ('0' as uint), - 'a' .. 'z' => c as uint + 10u - ('a' as uint), - 'A' .. 'Z' => c as uint + 10u - ('A' as uint), - _ => return None, - }; - if val < radix { Some(val) } - else { None } -} - -/// Convert a char to its uppercase equivalent -/// -/// The case-folding performed is the common or simple mapping: -/// it maps one unicode codepoint (one char in Rust) to its uppercase equivalent according -/// to the Unicode database at ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt -/// The additional SpecialCasing.txt is not considered here, as it expands to multiple -/// codepoints in some cases. -/// -/// A full reference can be found here -/// http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992 -/// -/// # Return value -/// -/// Returns the char itself if no conversion was made -#[inline] -pub fn to_uppercase(c: char) -> char { - conversions::to_upper(c) -} - -/// Convert a char 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 the char itself if no conversion if possible -#[inline] -pub fn to_lowercase(c: char) -> char { - conversions::to_lower(c) -} - -/// -/// Converts a number to the character representing it -/// -/// # Return value -/// -/// Returns `Some(char)` if `num` represents one digit under `radix`, -/// using one character of `0-9` or `a-z`, or `None` if it doesn't. -/// -/// # Failure -/// -/// Fails if given an `radix` > 36. -/// -#[inline] -pub fn from_digit(num: uint, radix: uint) -> Option { - if radix > 36 { - fail!("from_digit: radix {} is to high (maximum 36)", num); - } - if num < radix { - unsafe { - if num < 10 { - Some(transmute(('0' as uint + num) as u32)) - } else { - Some(transmute(('a' as uint + num - 10u) as u32)) - } - } - } else { - None - } -} - -// Constants from Unicode 6.2.0 Section 3.12 Conjoining Jamo Behavior -static S_BASE: uint = 0xAC00; -static L_BASE: uint = 0x1100; -static V_BASE: uint = 0x1161; -static T_BASE: uint = 0x11A7; -static L_COUNT: uint = 19; -static V_COUNT: uint = 21; -static T_COUNT: uint = 28; -static N_COUNT: uint = (V_COUNT * T_COUNT); -static S_COUNT: uint = (L_COUNT * N_COUNT); - -// Decompose a precomposed Hangul syllable -fn decompose_hangul(s: char, f: |char|) { - let si = s as uint - S_BASE; - - let li = si / N_COUNT; - unsafe { - f(transmute((L_BASE + li) as u32)); - - let vi = (si % N_COUNT) / T_COUNT; - f(transmute((V_BASE + vi) as u32)); - - let ti = si % T_COUNT; - if ti > 0 { - f(transmute((T_BASE + ti) as u32)); - } - } -} - -/// Returns the canonical decomposition of a character -pub fn decompose_canonical(c: char, f: |char|) { - if (c as uint) < S_BASE || (c as uint) >= (S_BASE + S_COUNT) { - decompose::canonical(c, f); - } else { - decompose_hangul(c, f); - } -} - -/// Returns the compatibility decomposition of a character -pub fn decompose_compatible(c: char, f: |char|) { - if (c as uint) < S_BASE || (c as uint) >= (S_BASE + S_COUNT) { - decompose::compatibility(c, f); - } else { - decompose_hangul(c, f); - } -} - -/// -/// Returns the hexadecimal Unicode escape of a `char` -/// -/// The rules are as follows: -/// -/// - chars in [0,0xff] get 2-digit escapes: `\\xNN` -/// - chars in [0x100,0xffff] get 4-digit escapes: `\\uNNNN` -/// - chars above 0x10000 get 8-digit escapes: `\\UNNNNNNNN` -/// -pub fn escape_unicode(c: char, f: |char|) { - // avoid calling str::to_str_radix because we don't really need to allocate - // here. - f('\\'); - let pad = match () { - _ if c <= '\xff' => { f('x'); 2 } - _ if c <= '\uffff' => { f('u'); 4 } - _ => { f('U'); 8 } - }; - for offset in range_step::(4 * (pad - 1), -1, -4) { - unsafe { - match ((c as i32) >> offset) & 0xf { - i @ 0 .. 9 => { f(transmute('0' as i32 + i)); } - i => { f(transmute('a' as i32 + (i - 10))); } - } - } - } -} - -/// -/// Returns a 'default' ASCII and C++11-like literal escape of a `char` -/// -/// 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`. -/// -pub fn escape_default(c: char, f: |char|) { - match c { - '\t' => { f('\\'); f('t'); } - '\r' => { f('\\'); f('r'); } - '\n' => { f('\\'); f('n'); } - '\\' => { f('\\'); f('\\'); } - '\'' => { f('\\'); f('\''); } - '"' => { f('\\'); f('"'); } - '\x20' .. '\x7e' => { f(c); } - _ => c.escape_unicode(f), - } -} - -/// Returns the amount of bytes this `char` would need if encoded in UTF-8 -pub fn len_utf8_bytes(c: char) -> uint { - static MAX_ONE_B: uint = 128u; - static MAX_TWO_B: uint = 2048u; - static MAX_THREE_B: uint = 65536u; - static MAX_FOUR_B: uint = 2097152u; - - let code = c as uint; - match () { - _ if code < MAX_ONE_B => 1u, - _ if code < MAX_TWO_B => 2u, - _ if code < MAX_THREE_B => 3u, - _ if code < MAX_FOUR_B => 4u, - _ => fail!("invalid character!"), - } -} - -/// Useful functions for Unicode characters. -pub trait Char { - /// Returns whether the specified character is considered a Unicode - /// alphabetic code point. - fn is_alphabetic(&self) -> bool; - - /// 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. - fn is_XID_start(&self) -> bool; - - /// 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. - fn is_XID_continue(&self) -> bool; - - - /// Indicates whether a character is in lowercase. - /// - /// This is defined according to the terms of the Unicode Derived Core - /// Property `Lowercase`. - fn is_lowercase(&self) -> bool; - - /// Indicates whether a character is in uppercase. - /// - /// This is defined according to the terms of the Unicode Derived Core - /// Property `Uppercase`. - fn is_uppercase(&self) -> bool; - - /// Indicates whether a character is whitespace. - /// - /// Whitespace is defined in terms of the Unicode Property `White_Space`. - fn is_whitespace(&self) -> bool; - - /// 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'. - fn is_alphanumeric(&self) -> bool; - - /// Indicates whether a character is a control code point. - /// - /// Control code points are defined in terms of the Unicode General - /// Category `Cc`. - fn is_control(&self) -> bool; - - /// Indicates whether the character is numeric (Nd, Nl, or No). - fn is_digit(&self) -> bool; - - /// Checks if a `char` parses as a numeric digit in the given radix. - /// - /// Compared to `is_digit()`, 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. - /// - /// # Failure - /// - /// Fails if given a radix > 36. - fn is_digit_radix(&self, radix: uint) -> bool; - - /// 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. - /// - /// # Failure - /// - /// Fails if given a radix outside the range [0..36]. - fn to_digit(&self, radix: uint) -> Option; - - /// 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 the lowercase equivalent of the character, or the character - /// itself if no conversion is possible. - fn to_lowercase(&self) -> char; - - /// Converts a character to its uppercase equivalent. - /// - /// The case-folding performed is the common or simple mapping: it maps - /// one unicode codepoint (one character in Rust) to its uppercase - /// equivalent according to the Unicode database [1]. The additional - /// `SpecialCasing.txt` is not considered here, as it expands to multiple - /// codepoints in some cases. - /// - /// A full reference can be found here [2]. - /// - /// # Return value - /// - /// Returns the uppercase equivalent of the character, or the character - /// itself if no conversion was made. - /// - /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt - /// - /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992 - fn to_uppercase(&self) -> char; - - /// Converts a number to the character representing it. - /// - /// # Return value - /// - /// Returns `Some(char)` if `num` represents one digit under `radix`, - /// using one character of `0-9` or `a-z`, or `None` if it doesn't. - /// - /// # Failure - /// - /// Fails if given a radix > 36. - fn from_digit(num: uint, radix: uint) -> Option; - - /// Returns the hexadecimal Unicode escape of a character. - /// - /// The rules are as follows: - /// - /// * Characters in [0,0xff] get 2-digit escapes: `\\xNN` - /// * Characters in [0x100,0xffff] get 4-digit escapes: `\\uNNNN`. - /// * Characters above 0x10000 get 8-digit escapes: `\\UNNNNNNNN`. - fn escape_unicode(&self, f: |char|); - - /// Returns a 'default' ASCII and C++11-like literal escape of a - /// character. - /// - /// 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`. - fn escape_default(&self, f: |char|); - - /// Returns the amount of bytes this character would need if encoded in - /// UTF-8. - fn len_utf8_bytes(&self) -> uint; - - /// Encodes this character as UTF-8 into the provided byte buffer. - /// - /// The buffer must be at least 4 bytes long or a runtime failure may - /// occur. - /// - /// This will then return the number of bytes written to the slice. - fn encode_utf8(&self, dst: &mut [u8]) -> uint; - - /// Encodes this character as UTF-16 into the provided `u16` buffer. - /// - /// The buffer must be at least 2 elements long or a runtime failure may - /// occur. - /// - /// This will then return the number of `u16`s written to the slice. - fn encode_utf16(&self, dst: &mut [u16]) -> uint; -} - -impl Char for char { - fn is_alphabetic(&self) -> bool { is_alphabetic(*self) } - - fn is_XID_start(&self) -> bool { is_XID_start(*self) } - - fn is_XID_continue(&self) -> bool { is_XID_continue(*self) } - - fn is_lowercase(&self) -> bool { is_lowercase(*self) } - - fn is_uppercase(&self) -> bool { is_uppercase(*self) } - - fn is_whitespace(&self) -> bool { is_whitespace(*self) } - - fn is_alphanumeric(&self) -> bool { is_alphanumeric(*self) } - - fn is_control(&self) -> bool { is_control(*self) } - - fn is_digit(&self) -> bool { is_digit(*self) } - - fn is_digit_radix(&self, radix: uint) -> bool { is_digit_radix(*self, radix) } - - fn to_digit(&self, radix: uint) -> Option { to_digit(*self, radix) } - - fn to_lowercase(&self) -> char { to_lowercase(*self) } - - fn to_uppercase(&self) -> char { to_uppercase(*self) } - - fn from_digit(num: uint, radix: uint) -> Option { from_digit(num, radix) } - - fn escape_unicode(&self, f: |char|) { escape_unicode(*self, f) } - - fn escape_default(&self, f: |char|) { escape_default(*self, f) } - - fn len_utf8_bytes(&self) -> uint { len_utf8_bytes(*self) } - - fn encode_utf8(&self, dst: &mut [u8]) -> uint { - let code = *self as uint; - if code < MAX_ONE_B { - dst[0] = code as u8; - return 1; - } else if code < MAX_TWO_B { - dst[0] = (code >> 6u & 31u | TAG_TWO_B) as u8; - dst[1] = (code & 63u | TAG_CONT) as u8; - return 2; - } else if code < MAX_THREE_B { - dst[0] = (code >> 12u & 15u | TAG_THREE_B) as u8; - dst[1] = (code >> 6u & 63u | TAG_CONT) as u8; - dst[2] = (code & 63u | TAG_CONT) as u8; - return 3; - } else { - dst[0] = (code >> 18u & 7u | TAG_FOUR_B) as u8; - dst[1] = (code >> 12u & 63u | TAG_CONT) as u8; - dst[2] = (code >> 6u & 63u | TAG_CONT) as u8; - dst[3] = (code & 63u | TAG_CONT) as u8; - return 4; - } - } - - fn encode_utf16(&self, dst: &mut [u16]) -> uint { - let mut ch = *self as uint; - if (ch & 0xFFFF_u) == ch { - // The BMP falls through (assuming non-surrogate, as it - // should) - assert!(ch <= 0xD7FF_u || ch >= 0xE000_u); - dst[0] = ch as u16; - 1 - } else { - // Supplementary planes break into surrogates. - assert!(ch >= 0x1_0000_u && ch <= 0x10_FFFF_u); - ch -= 0x1_0000_u; - dst[0] = 0xD800_u16 | ((ch >> 10) as u16); - dst[1] = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); - 2 - } - } -} - -#[cfg(not(test))] -impl Eq for char { - #[inline] - fn eq(&self, other: &char) -> bool { (*self) == (*other) } -} - -#[cfg(not(test))] -impl Ord for char { - #[inline] - fn lt(&self, other: &char) -> bool { *self < *other } -} - -#[cfg(not(test))] -impl Default for char { - #[inline] - fn default() -> char { '\x00' } -} - -#[test] -fn test_is_lowercase() { - assert!('a'.is_lowercase()); - assert!('ö'.is_lowercase()); - assert!('ß'.is_lowercase()); - assert!(!'Ü'.is_lowercase()); - assert!(!'P'.is_lowercase()); -} - -#[test] -fn test_is_uppercase() { - assert!(!'h'.is_uppercase()); - assert!(!'ä'.is_uppercase()); - assert!(!'ß'.is_uppercase()); - assert!('Ö'.is_uppercase()); - assert!('T'.is_uppercase()); -} - -#[test] -fn test_is_whitespace() { - assert!(' '.is_whitespace()); - assert!('\u2007'.is_whitespace()); - assert!('\t'.is_whitespace()); - assert!('\n'.is_whitespace()); - assert!(!'a'.is_whitespace()); - assert!(!'_'.is_whitespace()); - assert!(!'\u0000'.is_whitespace()); -} - -#[test] -fn test_to_digit() { - assert_eq!('0'.to_digit(10u), Some(0u)); - assert_eq!('1'.to_digit(2u), Some(1u)); - assert_eq!('2'.to_digit(3u), Some(2u)); - assert_eq!('9'.to_digit(10u), Some(9u)); - assert_eq!('a'.to_digit(16u), Some(10u)); - assert_eq!('A'.to_digit(16u), Some(10u)); - assert_eq!('b'.to_digit(16u), Some(11u)); - assert_eq!('B'.to_digit(16u), Some(11u)); - assert_eq!('z'.to_digit(36u), Some(35u)); - assert_eq!('Z'.to_digit(36u), Some(35u)); - assert_eq!(' '.to_digit(10u), None); - assert_eq!('$'.to_digit(36u), None); -} - -#[test] -fn test_to_lowercase() { - assert_eq!('A'.to_lowercase(), 'a'); - assert_eq!('Ö'.to_lowercase(), 'ö'); - assert_eq!('ß'.to_lowercase(), 'ß'); - assert_eq!('Ü'.to_lowercase(), 'ü'); - assert_eq!('💩'.to_lowercase(), '💩'); - assert_eq!('Σ'.to_lowercase(), 'σ'); - assert_eq!('Τ'.to_lowercase(), 'τ'); - assert_eq!('Ι'.to_lowercase(), 'ι'); - assert_eq!('Γ'.to_lowercase(), 'γ'); - assert_eq!('Μ'.to_lowercase(), 'μ'); - assert_eq!('Α'.to_lowercase(), 'α'); - assert_eq!('Σ'.to_lowercase(), 'σ'); -} - -#[test] -fn test_to_uppercase() { - assert_eq!('a'.to_uppercase(), 'A'); - assert_eq!('ö'.to_uppercase(), 'Ö'); - assert_eq!('ß'.to_uppercase(), 'ß'); // not ẞ: Latin capital letter sharp s - assert_eq!('ü'.to_uppercase(), 'Ü'); - assert_eq!('💩'.to_uppercase(), '💩'); - - assert_eq!('σ'.to_uppercase(), 'Σ'); - assert_eq!('τ'.to_uppercase(), 'Τ'); - assert_eq!('ι'.to_uppercase(), 'Ι'); - assert_eq!('γ'.to_uppercase(), 'Γ'); - assert_eq!('μ'.to_uppercase(), 'Μ'); - assert_eq!('α'.to_uppercase(), 'Α'); - assert_eq!('ς'.to_uppercase(), 'Σ'); -} - -#[test] -fn test_is_control() { - assert!('\u0000'.is_control()); - assert!('\u0003'.is_control()); - assert!('\u0006'.is_control()); - assert!('\u0009'.is_control()); - assert!('\u007f'.is_control()); - assert!('\u0092'.is_control()); - assert!(!'\u0020'.is_control()); - assert!(!'\u0055'.is_control()); - assert!(!'\u0068'.is_control()); -} - -#[test] -fn test_is_digit() { - assert!('2'.is_digit()); - assert!('7'.is_digit()); - assert!(!'c'.is_digit()); - assert!(!'i'.is_digit()); - assert!(!'z'.is_digit()); - assert!(!'Q'.is_digit()); -} - -#[test] -fn test_escape_default() { - fn string(c: char) -> ~str { - let mut result = StrBuf::new(); - escape_default(c, |c| { result.push_char(c); }); - return result.into_owned(); - } - assert_eq!(string('\n'), "\\n".to_owned()); - assert_eq!(string('\r'), "\\r".to_owned()); - assert_eq!(string('\''), "\\'".to_owned()); - assert_eq!(string('"'), "\\\"".to_owned()); - assert_eq!(string(' '), " ".to_owned()); - assert_eq!(string('a'), "a".to_owned()); - assert_eq!(string('~'), "~".to_owned()); - assert_eq!(string('\x00'), "\\x00".to_owned()); - assert_eq!(string('\x1f'), "\\x1f".to_owned()); - assert_eq!(string('\x7f'), "\\x7f".to_owned()); - assert_eq!(string('\xff'), "\\xff".to_owned()); - assert_eq!(string('\u011b'), "\\u011b".to_owned()); - assert_eq!(string('\U0001d4b6'), "\\U0001d4b6".to_owned()); -} - -#[test] -fn test_escape_unicode() { - fn string(c: char) -> ~str { - let mut result = StrBuf::new(); - escape_unicode(c, |c| { result.push_char(c); }); - return result.into_owned(); - } - assert_eq!(string('\x00'), "\\x00".to_owned()); - assert_eq!(string('\n'), "\\x0a".to_owned()); - assert_eq!(string(' '), "\\x20".to_owned()); - assert_eq!(string('a'), "\\x61".to_owned()); - assert_eq!(string('\u011b'), "\\u011b".to_owned()); - assert_eq!(string('\U0001d4b6'), "\\U0001d4b6".to_owned()); -} - -#[test] -fn test_to_str() { - use to_str::ToStr; - let s = 't'.to_str(); - assert_eq!(s, "t".to_owned()); -} - -#[test] -fn test_encode_utf8() { - fn check(input: char, expect: &[u8]) { - let mut buf = [0u8, ..4]; - let n = input.encode_utf8(buf /* as mut slice! */); - assert_eq!(buf.slice_to(n), expect); - } - - check('x', [0x78]); - check('\u00e9', [0xc3, 0xa9]); - check('\ua66e', [0xea, 0x99, 0xae]); - check('\U0001f4a9', [0xf0, 0x9f, 0x92, 0xa9]); -} - -#[test] -fn test_encode_utf16() { - fn check(input: char, expect: &[u16]) { - let mut buf = [0u16, ..2]; - let n = input.encode_utf16(buf /* as mut slice! */); - assert_eq!(buf.slice_to(n), expect); - } - - check('x', [0x0078]); - check('\u00e9', [0x00e9]); - check('\ua66e', [0xa66e]); - check('\U0001f4a9', [0xd83d, 0xdca9]); -} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 44684ba97c2..26e8e18909c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -138,6 +138,7 @@ extern crate core; #[cfg(not(test))] pub use ty = core::ty; pub use core::cast; +pub use core::char; pub use core::container; pub use core::intrinsics; pub use core::mem; @@ -188,7 +189,6 @@ pub mod prelude; pub mod unit; pub mod bool; -pub mod char; pub mod tuple; pub mod slice; -- cgit 1.4.1-3-g733a5 From 8ed728babb057c0f736a63a69ba772e45278148f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:36:58 -0700 Subject: core: Inherit the any module --- src/libcore/any.rs | 305 +++++++++++++++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 1 + src/libstd/any.rs | 322 -------------------------------------------------- src/libstd/fmt/mod.rs | 8 ++ src/libstd/lib.rs | 3 +- 5 files changed, 315 insertions(+), 324 deletions(-) create mode 100644 src/libcore/any.rs delete mode 100644 src/libstd/any.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/any.rs b/src/libcore/any.rs new file mode 100644 index 00000000000..f22453eb740 --- /dev/null +++ b/src/libcore/any.rs @@ -0,0 +1,305 @@ +// 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. + +//! Traits for dynamic typing of any type (through runtime reflection) +//! +//! This module implements the `Any` trait, which enables dynamic typing +//! of any type, through runtime reflection. +//! +//! `Any` itself can be used to get a `TypeId`, and has more features when used as a trait object. +//! As `&Any` (a borrowed trait object), it has the `is` and `as_ref` methods, to test if the +//! contained value is of a given type, and to get a reference to the inner value as a type. As +//! `&mut Any`, there is also the `as_mut` method, for getting a mutable reference to the inner +//! value. `Box` adds the `move` method, which will unwrap a `Box` from the object. See +//! the extension traits (`*Ext`) for the full details. + +use cast::{transmute, transmute_copy}; +use option::{Option, Some, None}; +use owned::Box; +use raw::TraitObject; +use result::{Result, Ok, Err}; +use intrinsics::TypeId; +use intrinsics; + +/// A type with no inhabitants +pub enum Void { } + +/////////////////////////////////////////////////////////////////////////////// +// Any trait +/////////////////////////////////////////////////////////////////////////////// + +/// The `Any` trait is implemented by all types, and can be used as a trait object +/// for dynamic typing +pub trait Any { + /// Get the `TypeId` of `self` + fn get_type_id(&self) -> TypeId; +} + +impl Any for T { + /// Get the `TypeId` of `self` + fn get_type_id(&self) -> TypeId { + TypeId::of::() + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Extension methods for Any trait objects. +// Implemented as three extension traits so that the methods can be generic. +/////////////////////////////////////////////////////////////////////////////// + +/// Extension methods for a referenced `Any` trait object +pub trait AnyRefExt<'a> { + /// Returns true if the boxed type is the same as `T` + fn is(self) -> bool; + + /// Returns some reference to the boxed value if it is of type `T`, or + /// `None` if it isn't. + fn as_ref(self) -> Option<&'a T>; +} + +impl<'a> AnyRefExt<'a> for &'a Any { + #[inline] + fn is(self) -> bool { + // Get TypeId of the type this function is instantiated with + let t = TypeId::of::(); + + // Get TypeId of the type in the trait object + let boxed = self.get_type_id(); + + // Compare both TypeIds on equality + t == boxed + } + + #[inline] + fn as_ref(self) -> Option<&'a T> { + if self.is::() { + unsafe { + // Get the raw representation of the trait object + let to: TraitObject = transmute_copy(&self); + + // Extract the data pointer + Some(transmute(to.data)) + } + } else { + None + } + } +} + +/// Extension methods for a mutable referenced `Any` trait object +pub trait AnyMutRefExt<'a> { + /// Returns some mutable reference to the boxed value if it is of type `T`, or + /// `None` if it isn't. + fn as_mut(self) -> Option<&'a mut T>; +} + +impl<'a> AnyMutRefExt<'a> for &'a mut Any { + #[inline] + fn as_mut(self) -> Option<&'a mut T> { + if self.is::() { + unsafe { + // Get the raw representation of the trait object + let to: TraitObject = transmute_copy(&self); + + // Extract the data pointer + Some(transmute(to.data)) + } + } else { + None + } + } +} + +/// Extension methods for an owning `Any` trait object +pub trait AnyOwnExt { + /// Returns the boxed value if it is of type `T`, or + /// `Err(Self)` if it isn't. + fn move(self) -> Result, Self>; +} + +impl AnyOwnExt for Box { + #[inline] + fn move(self) -> Result, Box> { + if self.is::() { + unsafe { + // Get the raw representation of the trait object + let to: TraitObject = transmute_copy(&self); + + // Prevent destructor on self being run + intrinsics::forget(self); + + // Extract the data pointer + Ok(transmute(to.data)) + } + } else { + Err(self) + } + } +} + +#[cfg(test)] +mod tests { + use prelude::*; + use super::*; + use owned::Box; + use str::StrSlice; + + #[deriving(Eq, Show)] + struct Test; + + static TEST: &'static str = "Test"; + + #[test] + fn any_referenced() { + let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any); + + assert!(a.is::()); + assert!(!b.is::()); + assert!(!c.is::()); + + assert!(!a.is::<&'static str>()); + assert!(b.is::<&'static str>()); + assert!(!c.is::<&'static str>()); + + assert!(!a.is::()); + assert!(!b.is::()); + assert!(c.is::()); + } + + #[test] + fn any_owning() { + let (a, b, c) = (box 5u as Box, box TEST as Box, box Test as Box); + + assert!(a.is::()); + assert!(!b.is::()); + assert!(!c.is::()); + + assert!(!a.is::<&'static str>()); + assert!(b.is::<&'static str>()); + assert!(!c.is::<&'static str>()); + + assert!(!a.is::()); + assert!(!b.is::()); + assert!(c.is::()); + } + + #[test] + fn any_as_ref() { + let a = &5u as &Any; + + match a.as_ref::() { + Some(&5) => {} + x => fail!("Unexpected value {:?}", x) + } + + match a.as_ref::() { + None => {} + x => fail!("Unexpected value {:?}", x) + } + } + + #[test] + fn any_as_mut() { + let mut a = 5u; + let mut b = box 7u; + + let a_r = &mut a as &mut Any; + let tmp: &mut uint = b; + let b_r = tmp as &mut Any; + + match a_r.as_mut::() { + Some(x) => { + assert_eq!(*x, 5u); + *x = 612; + } + x => fail!("Unexpected value {:?}", x) + } + + match b_r.as_mut::() { + Some(x) => { + assert_eq!(*x, 7u); + *x = 413; + } + x => fail!("Unexpected value {:?}", x) + } + + match a_r.as_mut::() { + None => (), + x => fail!("Unexpected value {:?}", x) + } + + match b_r.as_mut::() { + None => (), + x => fail!("Unexpected value {:?}", x) + } + + match a_r.as_mut::() { + Some(&612) => {} + x => fail!("Unexpected value {:?}", x) + } + + match b_r.as_mut::() { + Some(&413) => {} + x => fail!("Unexpected value {:?}", x) + } + } + + #[test] + fn any_move() { + let a = box 8u as Box; + let b = box Test as Box; + + match a.move::() { + Ok(a) => { assert_eq!(a, box 8u); } + Err(..) => fail!() + } + match b.move::() { + Ok(a) => { assert_eq!(a, box Test); } + Err(..) => fail!() + } + + let a = box 8u as Box; + let b = box Test as Box; + + assert!(a.move::>().is_err()); + assert!(b.move::>().is_err()); + } + + #[test] + fn test_show() { + let a = box 8u as Box; + let b = box Test as Box; + assert_eq!(format!("{}", a), "Box".to_owned()); + assert_eq!(format!("{}", b), "Box".to_owned()); + + let a = &8u as &Any; + let b = &Test as &Any; + assert_eq!(format!("{}", a), "&Any".to_owned()); + assert_eq!(format!("{}", b), "&Any".to_owned()); + } +} + +#[cfg(test)] +mod bench { + extern crate test; + + use any::{Any, AnyRefExt}; + use option::Some; + use self::test::Bencher; + + #[bench] + fn bench_as_ref(b: &mut Bencher) { + b.iter(|| { + let mut x = 0; let mut y = &mut x as &mut Any; + test::black_box(&mut y); + test::black_box(y.as_ref::() == Some(&0)); + }); + } +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 5206ba1f32a..08b0434d827 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -37,5 +37,6 @@ pub mod container; /* Core types and methods on primitives */ +pub mod any; pub mod finally; pub mod char; diff --git a/src/libstd/any.rs b/src/libstd/any.rs deleted file mode 100644 index 2c1ce9fa779..00000000000 --- a/src/libstd/any.rs +++ /dev/null @@ -1,322 +0,0 @@ -// 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. - -//! Traits for dynamic typing of any type (through runtime reflection) -//! -//! This module implements the `Any` trait, which enables dynamic typing -//! of any type, through runtime reflection. -//! -//! `Any` itself can be used to get a `TypeId`, and has more features when used as a trait object. -//! As `&Any` (a borrowed trait object), it has the `is` and `as_ref` methods, to test if the -//! contained value is of a given type, and to get a reference to the inner value as a type. As -//! `&mut Any`, there is also the `as_mut` method, for getting a mutable reference to the inner -//! value. `Box` adds the `move` method, which will unwrap a `Box` from the object. See -//! the extension traits (`*Ext`) for the full details. - -use cast::{transmute, transmute_copy}; -use fmt; -use option::{Option, Some, None}; -use owned::Box; -use raw::TraitObject; -use result::{Result, Ok, Err}; -use intrinsics::TypeId; -use intrinsics; - -/// A type with no inhabitants -pub enum Void { } - -/////////////////////////////////////////////////////////////////////////////// -// Any trait -/////////////////////////////////////////////////////////////////////////////// - -/// The `Any` trait is implemented by all types, and can be used as a trait object -/// for dynamic typing -pub trait Any { - /// Get the `TypeId` of `self` - fn get_type_id(&self) -> TypeId; -} - -impl Any for T { - /// Get the `TypeId` of `self` - fn get_type_id(&self) -> TypeId { - TypeId::of::() - } -} - -/////////////////////////////////////////////////////////////////////////////// -// Extension methods for Any trait objects. -// Implemented as three extension traits so that the methods can be generic. -/////////////////////////////////////////////////////////////////////////////// - -/// Extension methods for a referenced `Any` trait object -pub trait AnyRefExt<'a> { - /// Returns true if the boxed type is the same as `T` - fn is(self) -> bool; - - /// Returns some reference to the boxed value if it is of type `T`, or - /// `None` if it isn't. - fn as_ref(self) -> Option<&'a T>; -} - -impl<'a> AnyRefExt<'a> for &'a Any { - #[inline] - fn is(self) -> bool { - // Get TypeId of the type this function is instantiated with - let t = TypeId::of::(); - - // Get TypeId of the type in the trait object - let boxed = self.get_type_id(); - - // Compare both TypeIds on equality - t == boxed - } - - #[inline] - fn as_ref(self) -> Option<&'a T> { - if self.is::() { - unsafe { - // Get the raw representation of the trait object - let to: TraitObject = transmute_copy(&self); - - // Extract the data pointer - Some(transmute(to.data)) - } - } else { - None - } - } -} - -/// Extension methods for a mutable referenced `Any` trait object -pub trait AnyMutRefExt<'a> { - /// Returns some mutable reference to the boxed value if it is of type `T`, or - /// `None` if it isn't. - fn as_mut(self) -> Option<&'a mut T>; -} - -impl<'a> AnyMutRefExt<'a> for &'a mut Any { - #[inline] - fn as_mut(self) -> Option<&'a mut T> { - if self.is::() { - unsafe { - // Get the raw representation of the trait object - let to: TraitObject = transmute_copy(&self); - - // Extract the data pointer - Some(transmute(to.data)) - } - } else { - None - } - } -} - -/// Extension methods for an owning `Any` trait object -pub trait AnyOwnExt { - /// Returns the boxed value if it is of type `T`, or - /// `Err(Self)` if it isn't. - fn move(self) -> Result, Self>; -} - -impl AnyOwnExt for Box { - #[inline] - fn move(self) -> Result, Box> { - if self.is::() { - unsafe { - // Get the raw representation of the trait object - let to: TraitObject = transmute_copy(&self); - - // Prevent destructor on self being run - intrinsics::forget(self); - - // Extract the data pointer - Ok(transmute(to.data)) - } - } else { - Err(self) - } - } -} - -/////////////////////////////////////////////////////////////////////////////// -// Trait implementations -/////////////////////////////////////////////////////////////////////////////// - -impl fmt::Show for Box { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("Box") - } -} - -impl<'a> fmt::Show for &'a Any { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("&Any") - } -} - -#[cfg(test)] -mod tests { - use prelude::*; - use super::*; - use owned::Box; - use str::StrSlice; - - #[deriving(Eq, Show)] - struct Test; - - static TEST: &'static str = "Test"; - - #[test] - fn any_referenced() { - let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any); - - assert!(a.is::()); - assert!(!b.is::()); - assert!(!c.is::()); - - assert!(!a.is::<&'static str>()); - assert!(b.is::<&'static str>()); - assert!(!c.is::<&'static str>()); - - assert!(!a.is::()); - assert!(!b.is::()); - assert!(c.is::()); - } - - #[test] - fn any_owning() { - let (a, b, c) = (box 5u as Box, box TEST as Box, box Test as Box); - - assert!(a.is::()); - assert!(!b.is::()); - assert!(!c.is::()); - - assert!(!a.is::<&'static str>()); - assert!(b.is::<&'static str>()); - assert!(!c.is::<&'static str>()); - - assert!(!a.is::()); - assert!(!b.is::()); - assert!(c.is::()); - } - - #[test] - fn any_as_ref() { - let a = &5u as &Any; - - match a.as_ref::() { - Some(&5) => {} - x => fail!("Unexpected value {:?}", x) - } - - match a.as_ref::() { - None => {} - x => fail!("Unexpected value {:?}", x) - } - } - - #[test] - fn any_as_mut() { - let mut a = 5u; - let mut b = box 7u; - - let a_r = &mut a as &mut Any; - let tmp: &mut uint = b; - let b_r = tmp as &mut Any; - - match a_r.as_mut::() { - Some(x) => { - assert_eq!(*x, 5u); - *x = 612; - } - x => fail!("Unexpected value {:?}", x) - } - - match b_r.as_mut::() { - Some(x) => { - assert_eq!(*x, 7u); - *x = 413; - } - x => fail!("Unexpected value {:?}", x) - } - - match a_r.as_mut::() { - None => (), - x => fail!("Unexpected value {:?}", x) - } - - match b_r.as_mut::() { - None => (), - x => fail!("Unexpected value {:?}", x) - } - - match a_r.as_mut::() { - Some(&612) => {} - x => fail!("Unexpected value {:?}", x) - } - - match b_r.as_mut::() { - Some(&413) => {} - x => fail!("Unexpected value {:?}", x) - } - } - - #[test] - fn any_move() { - let a = box 8u as Box; - let b = box Test as Box; - - match a.move::() { - Ok(a) => { assert_eq!(a, box 8u); } - Err(..) => fail!() - } - match b.move::() { - Ok(a) => { assert_eq!(a, box Test); } - Err(..) => fail!() - } - - let a = box 8u as Box; - let b = box Test as Box; - - assert!(a.move::>().is_err()); - assert!(b.move::>().is_err()); - } - - #[test] - fn test_show() { - let a = box 8u as Box; - let b = box Test as Box; - assert_eq!(format!("{}", a), "Box".to_owned()); - assert_eq!(format!("{}", b), "Box".to_owned()); - - let a = &8u as &Any; - let b = &Test as &Any; - assert_eq!(format!("{}", a), "&Any".to_owned()); - assert_eq!(format!("{}", b), "&Any".to_owned()); - } -} - -#[cfg(test)] -mod bench { - extern crate test; - - use any::{Any, AnyRefExt}; - use option::Some; - use self::test::Bencher; - - #[bench] - fn bench_as_ref(b: &mut Bencher) { - b.iter(|| { - let mut x = 0; let mut y = &mut x as &mut Any; - test::black_box(&mut y); - test::black_box(y.as_ref::() == Some(&0)); - }); - } -} diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index 53d6f2fc0d2..8c999c2e2e3 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -1242,6 +1242,14 @@ impl Show for *mut T { fn fmt(&self, f: &mut Formatter) -> Result { secret_pointer(self, f) } } +impl Show for Box { + fn fmt(&self, f: &mut Formatter) -> Result { f.pad("Box") } +} + +impl<'a> Show for &'a any::Any { + fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") } +} + impl Show for TypeId { fn fmt(&self, f: &mut Formatter) -> Result { write!(f.buf, "TypeId \\{ {} \\}", self.hash()) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 26e8e18909c..356b653281e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -137,6 +137,7 @@ extern crate core; #[cfg(not(test))] pub use ops = core::ops; #[cfg(not(test))] pub use ty = core::ty; +pub use core::any; pub use core::cast; pub use core::char; pub use core::container; @@ -218,8 +219,6 @@ pub mod iter; pub mod to_str; pub mod clone; pub mod hash; -pub mod default; -pub mod any; /* Common data structures */ -- cgit 1.4.1-3-g733a5 From 17cb238ee80726c057a16c90b8c4e7e8bfd25c9d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:38:31 -0700 Subject: core: Inherit the raw module --- src/libcore/lib.rs | 1 + src/libcore/raw.rs | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/lib.rs | 3 +- src/libstd/raw.rs | 113 ---------------------------------------------------- 4 files changed, 116 insertions(+), 115 deletions(-) create mode 100644 src/libcore/raw.rs delete mode 100644 src/libstd/raw.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 08b0434d827..fe4809a5001 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -39,4 +39,5 @@ pub mod container; pub mod any; pub mod finally; +pub mod raw; pub mod char; diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs new file mode 100644 index 00000000000..d6caa145ae9 --- /dev/null +++ b/src/libcore/raw.rs @@ -0,0 +1,114 @@ +// Copyright 2013 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(missing_doc)] +#![experimental] + +//! Contains struct definitions for the layout of compiler built-in types. +//! +//! They can be used as targets of transmutes in unsafe code for manipulating +//! the raw representations directly. +//! +//! Their definition should always match the ABI defined in `rustc::back::abi`. + +use cast; + +/// The representation of a Rust managed box +pub struct Box { + pub ref_count: uint, + pub drop_glue: fn(ptr: *mut u8), + pub prev: *mut Box, + pub next: *mut Box, + pub data: T, +} + +/// The representation of a Rust vector +pub struct Vec { + pub fill: uint, + pub alloc: uint, + pub data: T, +} + +/// The representation of a Rust string +pub type String = Vec; + +/// The representation of a Rust slice +pub struct Slice { + pub data: *T, + pub len: uint, +} + +/// The representation of a Rust closure +pub struct Closure { + pub code: *(), + pub env: *(), +} + +/// The representation of a Rust procedure (`proc()`) +pub struct Procedure { + pub code: *(), + pub env: *(), +} + +/// The representation of a Rust trait object. +/// +/// This struct does not have a `Repr` implementation +/// because there is no way to refer to all trait objects generically. +pub struct TraitObject { + pub vtable: *(), + pub data: *(), +} + +/// This trait is meant to map equivalences between raw structs and their +/// corresponding rust values. +pub trait Repr { + /// This function "unwraps" a rust value (without consuming it) into its raw + /// struct representation. This can be used to read/write different values + /// for the struct. This is a safe method because by default it does not + /// enable write-access to the fields of the return value in safe code. + #[inline] + fn repr(&self) -> T { unsafe { cast::transmute_copy(self) } } +} + +impl<'a, T> Repr> for &'a [T] {} +impl<'a> Repr> for &'a str {} +impl Repr<*Box> for @T {} +impl Repr<*Vec> for ~[T] {} +impl Repr<*String> for ~str {} + +#[cfg(test)] +mod tests { + use super::*; + + use cast; + + #[test] + fn synthesize_closure() { + unsafe { + let x = 10; + let f: |int| -> int = |y| x + y; + + assert_eq!(f(20), 30); + + let original_closure: Closure = cast::transmute(f); + + let actual_function_pointer = original_closure.code; + let environment = original_closure.env; + + let new_closure = Closure { + code: actual_function_pointer, + env: environment + }; + + let new_f: |int| -> int = cast::transmute(new_closure); + assert_eq!(new_f(20), 30); + } + } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 356b653281e..4485da81969 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -144,6 +144,7 @@ pub use core::container; pub use core::intrinsics; pub use core::mem; pub use core::ptr; +pub use core::raw; // Run tests with libgreen instead of libnative. // @@ -255,8 +256,6 @@ pub mod reflect; // Private APIs #[unstable] pub mod unstable; -#[experimental] -pub mod raw; /* For internal use, not exported */ diff --git a/src/libstd/raw.rs b/src/libstd/raw.rs deleted file mode 100644 index 9b0463089d0..00000000000 --- a/src/libstd/raw.rs +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2013 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(missing_doc)] - -//! Contains struct definitions for the layout of compiler built-in types. -//! -//! They can be used as targets of transmutes in unsafe code for manipulating -//! the raw representations directly. -//! -//! Their definition should always match the ABI defined in `rustc::back::abi`. - -use cast; - -/// The representation of a Rust managed box -pub struct Box { - pub ref_count: uint, - pub drop_glue: fn(ptr: *mut u8), - pub prev: *mut Box, - pub next: *mut Box, - pub data: T, -} - -/// The representation of a Rust vector -pub struct Vec { - pub fill: uint, - pub alloc: uint, - pub data: T, -} - -/// The representation of a Rust string -pub type String = Vec; - -/// The representation of a Rust slice -pub struct Slice { - pub data: *T, - pub len: uint, -} - -/// The representation of a Rust closure -pub struct Closure { - pub code: *(), - pub env: *(), -} - -/// The representation of a Rust procedure (`proc()`) -pub struct Procedure { - pub code: *(), - pub env: *(), -} - -/// The representation of a Rust trait object. -/// -/// This struct does not have a `Repr` implementation -/// because there is no way to refer to all trait objects generically. -pub struct TraitObject { - pub vtable: *(), - pub data: *(), -} - -/// This trait is meant to map equivalences between raw structs and their -/// corresponding rust values. -pub trait Repr { - /// This function "unwraps" a rust value (without consuming it) into its raw - /// struct representation. This can be used to read/write different values - /// for the struct. This is a safe method because by default it does not - /// enable write-access to the fields of the return value in safe code. - #[inline] - fn repr(&self) -> T { unsafe { cast::transmute_copy(self) } } -} - -impl<'a, T> Repr> for &'a [T] {} -impl<'a> Repr> for &'a str {} -impl Repr<*Box> for @T {} -impl Repr<*Vec> for ~[T] {} -impl Repr<*String> for ~str {} - -#[cfg(test)] -mod tests { - use super::*; - - use cast; - - #[test] - fn synthesize_closure() { - unsafe { - let x = 10; - let f: |int| -> int = |y| x + y; - - assert_eq!(f(20), 30); - - let original_closure: Closure = cast::transmute(f); - - let actual_function_pointer = original_closure.code; - let environment = original_closure.env; - - let new_closure = Closure { - code: actual_function_pointer, - env: environment - }; - - let new_f: |int| -> int = cast::transmute(new_closure); - assert_eq!(new_f(20), 30); - } - } -} -- cgit 1.4.1-3-g733a5 From dfd967f239a079cf90f45bfc3d827547e6fe9008 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:46:51 -0700 Subject: core: Inherit the default module --- src/libcore/default.rs | 27 +++++++++++++++++++++++++++ src/libcore/lib.rs | 1 + src/libstd/default.rs | 27 --------------------------- src/libstd/lib.rs | 1 + 4 files changed, 29 insertions(+), 27 deletions(-) create mode 100644 src/libcore/default.rs delete mode 100644 src/libstd/default.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/default.rs b/src/libcore/default.rs new file mode 100644 index 00000000000..9cf3a763648 --- /dev/null +++ b/src/libcore/default.rs @@ -0,0 +1,27 @@ +// Copyright 2013 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. + +//! The `Default` trait for types which may have meaningful default values + +use owned::Box; + +/// A trait that types which have a useful default value should implement. +pub trait Default { + /// Return the "default value" for a type. + fn default() -> Self; +} + +impl Default for @T { + fn default() -> @T { @Default::default() } +} + +impl Default for Box { + fn default() -> Box { box Default::default() } +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index fe4809a5001..6730c252f52 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -33,6 +33,7 @@ pub mod ptr; pub mod kinds; pub mod ops; pub mod ty; +pub mod default; pub mod container; /* Core types and methods on primitives */ diff --git a/src/libstd/default.rs b/src/libstd/default.rs deleted file mode 100644 index 9cf3a763648..00000000000 --- a/src/libstd/default.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2013 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. - -//! The `Default` trait for types which may have meaningful default values - -use owned::Box; - -/// A trait that types which have a useful default value should implement. -pub trait Default { - /// Return the "default value" for a type. - fn default() -> Self; -} - -impl Default for @T { - fn default() -> @T { @Default::default() } -} - -impl Default for Box { - fn default() -> Box { box Default::default() } -} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 4485da81969..ef07fc2f995 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -141,6 +141,7 @@ pub use core::any; pub use core::cast; pub use core::char; pub use core::container; +pub use core::default; pub use core::intrinsics; pub use core::mem; pub use core::ptr; -- cgit 1.4.1-3-g733a5 From e7eed5f670e8b283e7afcba5c79b3b208167a647 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:50:56 -0700 Subject: core: Inherit the unit module --- src/libcore/lib.rs | 1 + src/libcore/unit.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++ src/libstd/fmt/mod.rs | 6 ++++++ src/libstd/lib.rs | 1 - src/libstd/unit.rs | 52 --------------------------------------------------- 5 files changed, 52 insertions(+), 53 deletions(-) create mode 100644 src/libcore/unit.rs delete mode 100644 src/libstd/unit.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 6730c252f52..8b3124b0166 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -38,6 +38,7 @@ pub mod container; /* Core types and methods on primitives */ +mod unit; pub mod any; pub mod finally; pub mod raw; diff --git a/src/libcore/unit.rs b/src/libcore/unit.rs new file mode 100644 index 00000000000..f55cb2d2236 --- /dev/null +++ b/src/libcore/unit.rs @@ -0,0 +1,45 @@ +// Copyright 2012-2013 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. + +//! Functions for the unit type. + +#[cfg(not(test))] +use default::Default; +#[cfg(not(test))] +use cmp::{Eq, Equal, Ord, Ordering, TotalEq, TotalOrd}; + +#[cfg(not(test))] +impl Eq for () { + #[inline] + fn eq(&self, _other: &()) -> bool { true } + #[inline] + fn ne(&self, _other: &()) -> bool { false } +} + +#[cfg(not(test))] +impl Ord for () { + #[inline] + fn lt(&self, _other: &()) -> bool { false } +} + +#[cfg(not(test))] +impl TotalOrd for () { + #[inline] + fn cmp(&self, _other: &()) -> Ordering { Equal } +} + +#[cfg(not(test))] +impl TotalEq for () {} + +#[cfg(not(test))] +impl Default for () { + #[inline] + fn default() -> () { () } +} diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index 8c999c2e2e3..7623da8734e 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -1250,6 +1250,12 @@ impl<'a> Show for &'a any::Any { fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") } } +impl Show for () { + fn fmt(&self, f: &mut Formatter) -> Result { + f.pad("()") + } +} + impl Show for TypeId { fn fmt(&self, f: &mut Formatter) -> Result { write!(f.buf, "TypeId \\{ {} \\}", self.hash()) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ef07fc2f995..5e71fc72dc9 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -190,7 +190,6 @@ pub mod prelude; #[path = "num/f32.rs"] pub mod f32; #[path = "num/f64.rs"] pub mod f64; -pub mod unit; pub mod bool; pub mod tuple; diff --git a/src/libstd/unit.rs b/src/libstd/unit.rs deleted file mode 100644 index 38307f415ac..00000000000 --- a/src/libstd/unit.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2012-2013 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. - -//! Functions for the unit type. - -#[cfg(not(test))] -use default::Default; -#[cfg(not(test))] -use cmp::{Eq, Equal, Ord, Ordering, TotalEq, TotalOrd}; -use fmt; - -#[cfg(not(test))] -impl Eq for () { - #[inline] - fn eq(&self, _other: &()) -> bool { true } - #[inline] - fn ne(&self, _other: &()) -> bool { false } -} - -#[cfg(not(test))] -impl Ord for () { - #[inline] - fn lt(&self, _other: &()) -> bool { false } -} - -#[cfg(not(test))] -impl TotalOrd for () { - #[inline] - fn cmp(&self, _other: &()) -> Ordering { Equal } -} - -#[cfg(not(test))] -impl TotalEq for () {} - -#[cfg(not(test))] -impl Default for () { - #[inline] - fn default() -> () { () } -} - -impl fmt::Show for () { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("()") - } -} -- cgit 1.4.1-3-g733a5 From 54b81997f367e8963d722c5e23bd7a877d0273cd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 20:55:38 -0700 Subject: core: Inherit the clone module --- src/libcore/clone.rs | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 1 + src/libstd/clone.rs | 171 --------------------------------------------------- src/libstd/lib.rs | 2 +- 4 files changed, 173 insertions(+), 172 deletions(-) create mode 100644 src/libcore/clone.rs delete mode 100644 src/libstd/clone.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs new file mode 100644 index 00000000000..36d1cd9ba94 --- /dev/null +++ b/src/libcore/clone.rs @@ -0,0 +1,171 @@ +// Copyright 2012-2013 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. + +/*! The `Clone` trait for types that cannot be 'implicitly copied' + +In Rust, some simple types are "implicitly copyable" and when you +assign them or pass them as arguments, the receiver will get a copy, +leaving the original value in place. These types do not require +allocation to copy and do not have finalizers (i.e. they do not +contain owned boxes or implement `Drop`), so the compiler considers +them cheap and safe to copy. For other types copies must be made +explicitly, by convention implementing the `Clone` trait and calling +the `clone` method. + +*/ + +use owned::Box; + +/// A common trait for cloning an object. +pub trait Clone { + /// Returns a copy of the value. The contents of owned pointers + /// are copied to maintain uniqueness, while the contents of + /// managed pointers are not copied. + fn clone(&self) -> Self; + + /// Perform copy-assignment from `source`. + /// + /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality, + /// but can be overridden to reuse the resources of `a` to avoid unnecessary + /// allocations. + #[inline(always)] + fn clone_from(&mut self, source: &Self) { + *self = source.clone() + } +} + +impl Clone for Box { + /// Return a copy of the owned box. + #[inline] + fn clone(&self) -> Box { box {(**self).clone()} } + + /// Perform copy-assignment from `source` by reusing the existing allocation. + #[inline] + fn clone_from(&mut self, source: &Box) { + (**self).clone_from(&(**source)); + } +} + +impl Clone for @T { + /// Return a shallow copy of the managed box. + #[inline] + fn clone(&self) -> @T { *self } +} + +impl<'a, T> Clone for &'a T { + /// Return a shallow copy of the reference. + #[inline] + fn clone(&self) -> &'a T { *self } +} + +impl<'a, T> Clone for &'a [T] { + /// Return a shallow copy of the slice. + #[inline] + fn clone(&self) -> &'a [T] { *self } +} + +impl<'a> Clone for &'a str { + /// Return a shallow copy of the slice. + #[inline] + fn clone(&self) -> &'a str { *self } +} + +macro_rules! clone_impl( + ($t:ty) => { + impl Clone for $t { + /// Return a deep copy of the value. + #[inline] + fn clone(&self) -> $t { *self } + } + } +) + +clone_impl!(int) +clone_impl!(i8) +clone_impl!(i16) +clone_impl!(i32) +clone_impl!(i64) + +clone_impl!(uint) +clone_impl!(u8) +clone_impl!(u16) +clone_impl!(u32) +clone_impl!(u64) + +clone_impl!(f32) +clone_impl!(f64) + +clone_impl!(()) +clone_impl!(bool) +clone_impl!(char) + +macro_rules! extern_fn_clone( + ($($A:ident),*) => ( + impl<$($A,)* ReturnType> Clone for extern "Rust" fn($($A),*) -> ReturnType { + /// Return a copy of a function pointer + #[inline] + fn clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self } + } + ) +) + +extern_fn_clone!() +extern_fn_clone!(A) +extern_fn_clone!(A, B) +extern_fn_clone!(A, B, C) +extern_fn_clone!(A, B, C, D) +extern_fn_clone!(A, B, C, D, E) +extern_fn_clone!(A, B, C, D, E, F) +extern_fn_clone!(A, B, C, D, E, F, G) +extern_fn_clone!(A, B, C, D, E, F, G, H) + +#[test] +fn test_owned_clone() { + let a = box 5i; + let b: Box = a.clone(); + assert_eq!(a, b); +} + +#[test] +fn test_managed_clone() { + let a = @5i; + let b: @int = a.clone(); + assert_eq!(a, b); +} + +#[test] +fn test_borrowed_clone() { + let x = 5i; + let y: &int = &x; + let z: &int = (&y).clone(); + assert_eq!(*z, 5); +} + +#[test] +fn test_clone_from() { + let a = box 5; + let mut b = box 10; + b.clone_from(&a); + assert_eq!(*b, 5); +} + +#[test] +fn test_extern_fn_clone() { + trait Empty {} + impl Empty for int {} + + fn test_fn_a() -> f64 { 1.0 } + fn test_fn_b(x: T) -> T { x } + fn test_fn_c(_: int, _: f64, _: ~[int], _: int, _: int, _: int) {} + + let _ = test_fn_a.clone(); + let _ = test_fn_b::.clone(); + let _ = test_fn_c.clone(); +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 8b3124b0166..cca2cf42879 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -33,6 +33,7 @@ pub mod ptr; pub mod kinds; pub mod ops; pub mod ty; +pub mod clone; pub mod default; pub mod container; diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs deleted file mode 100644 index 36d1cd9ba94..00000000000 --- a/src/libstd/clone.rs +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2012-2013 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. - -/*! The `Clone` trait for types that cannot be 'implicitly copied' - -In Rust, some simple types are "implicitly copyable" and when you -assign them or pass them as arguments, the receiver will get a copy, -leaving the original value in place. These types do not require -allocation to copy and do not have finalizers (i.e. they do not -contain owned boxes or implement `Drop`), so the compiler considers -them cheap and safe to copy. For other types copies must be made -explicitly, by convention implementing the `Clone` trait and calling -the `clone` method. - -*/ - -use owned::Box; - -/// A common trait for cloning an object. -pub trait Clone { - /// Returns a copy of the value. The contents of owned pointers - /// are copied to maintain uniqueness, while the contents of - /// managed pointers are not copied. - fn clone(&self) -> Self; - - /// Perform copy-assignment from `source`. - /// - /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality, - /// but can be overridden to reuse the resources of `a` to avoid unnecessary - /// allocations. - #[inline(always)] - fn clone_from(&mut self, source: &Self) { - *self = source.clone() - } -} - -impl Clone for Box { - /// Return a copy of the owned box. - #[inline] - fn clone(&self) -> Box { box {(**self).clone()} } - - /// Perform copy-assignment from `source` by reusing the existing allocation. - #[inline] - fn clone_from(&mut self, source: &Box) { - (**self).clone_from(&(**source)); - } -} - -impl Clone for @T { - /// Return a shallow copy of the managed box. - #[inline] - fn clone(&self) -> @T { *self } -} - -impl<'a, T> Clone for &'a T { - /// Return a shallow copy of the reference. - #[inline] - fn clone(&self) -> &'a T { *self } -} - -impl<'a, T> Clone for &'a [T] { - /// Return a shallow copy of the slice. - #[inline] - fn clone(&self) -> &'a [T] { *self } -} - -impl<'a> Clone for &'a str { - /// Return a shallow copy of the slice. - #[inline] - fn clone(&self) -> &'a str { *self } -} - -macro_rules! clone_impl( - ($t:ty) => { - impl Clone for $t { - /// Return a deep copy of the value. - #[inline] - fn clone(&self) -> $t { *self } - } - } -) - -clone_impl!(int) -clone_impl!(i8) -clone_impl!(i16) -clone_impl!(i32) -clone_impl!(i64) - -clone_impl!(uint) -clone_impl!(u8) -clone_impl!(u16) -clone_impl!(u32) -clone_impl!(u64) - -clone_impl!(f32) -clone_impl!(f64) - -clone_impl!(()) -clone_impl!(bool) -clone_impl!(char) - -macro_rules! extern_fn_clone( - ($($A:ident),*) => ( - impl<$($A,)* ReturnType> Clone for extern "Rust" fn($($A),*) -> ReturnType { - /// Return a copy of a function pointer - #[inline] - fn clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self } - } - ) -) - -extern_fn_clone!() -extern_fn_clone!(A) -extern_fn_clone!(A, B) -extern_fn_clone!(A, B, C) -extern_fn_clone!(A, B, C, D) -extern_fn_clone!(A, B, C, D, E) -extern_fn_clone!(A, B, C, D, E, F) -extern_fn_clone!(A, B, C, D, E, F, G) -extern_fn_clone!(A, B, C, D, E, F, G, H) - -#[test] -fn test_owned_clone() { - let a = box 5i; - let b: Box = a.clone(); - assert_eq!(a, b); -} - -#[test] -fn test_managed_clone() { - let a = @5i; - let b: @int = a.clone(); - assert_eq!(a, b); -} - -#[test] -fn test_borrowed_clone() { - let x = 5i; - let y: &int = &x; - let z: &int = (&y).clone(); - assert_eq!(*z, 5); -} - -#[test] -fn test_clone_from() { - let a = box 5; - let mut b = box 10; - b.clone_from(&a); - assert_eq!(*b, 5); -} - -#[test] -fn test_extern_fn_clone() { - trait Empty {} - impl Empty for int {} - - fn test_fn_a() -> f64 { 1.0 } - fn test_fn_b(x: T) -> T { x } - fn test_fn_c(_: int, _: f64, _: ~[int], _: int, _: int, _: int) {} - - let _ = test_fn_a.clone(); - let _ = test_fn_b::.clone(); - let _ = test_fn_c.clone(); -} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 5e71fc72dc9..aca182a02ea 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -140,6 +140,7 @@ extern crate core; pub use core::any; pub use core::cast; pub use core::char; +pub use core::clone; pub use core::container; pub use core::default; pub use core::intrinsics; @@ -218,7 +219,6 @@ pub mod from_str; pub mod num; pub mod iter; pub mod to_str; -pub mod clone; pub mod hash; /* Common data structures */ -- cgit 1.4.1-3-g733a5 From 92095d125ab4353a7bae002b893c2bd1bd06e379 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 21:02:13 -0700 Subject: core: Inherit the tuple module --- src/libcore/lib.rs | 1 + src/libcore/tuple.rs | 330 +++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/fmt/mod.rs | 30 +++++ src/libstd/lib.rs | 2 +- src/libstd/tuple.rs | 350 -------------------------------------------------- 5 files changed, 362 insertions(+), 351 deletions(-) create mode 100644 src/libcore/tuple.rs delete mode 100644 src/libstd/tuple.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index cca2cf42879..19f64c6d067 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -44,3 +44,4 @@ pub mod any; pub mod finally; pub mod raw; pub mod char; +pub mod tuple; diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs new file mode 100644 index 00000000000..84f850ff907 --- /dev/null +++ b/src/libcore/tuple.rs @@ -0,0 +1,330 @@ +// 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. + +//! Operations on tuples + +#![allow(missing_doc)] + +use clone::Clone; +#[cfg(not(test))] use cmp::*; +#[cfg(not(test))] use default::Default; + +// macro for implementing n-ary tuple functions and operations +macro_rules! tuple_impls { + ($( + $Tuple:ident { + $(($valN:ident, $refN:ident, $mutN:ident) -> $T:ident { + ($($x:ident),+) => $ret:expr + })+ + } + )+) => { + $( + pub trait $Tuple<$($T),+> { + $(fn $valN(self) -> $T;)+ + $(fn $refN<'a>(&'a self) -> &'a $T;)+ + $(fn $mutN<'a>(&'a mut self) -> &'a mut $T;)+ + } + + impl<$($T),+> $Tuple<$($T),+> for ($($T,)+) { + $( + #[inline] + #[allow(unused_variable)] + fn $valN(self) -> $T { + let ($($x,)+) = self; $ret + } + + #[inline] + #[allow(unused_variable)] + fn $refN<'a>(&'a self) -> &'a $T { + let ($(ref $x,)+) = *self; $ret + } + + #[inline] + #[allow(unused_variable)] + fn $mutN<'a>(&'a mut self) -> &'a mut $T { + let ($(ref mut $x,)+) = *self; $ret + } + )+ + } + + impl<$($T:Clone),+> Clone for ($($T,)+) { + fn clone(&self) -> ($($T,)+) { + ($(self.$refN().clone(),)+) + } + } + + #[cfg(not(test))] + impl<$($T:Eq),+> Eq for ($($T,)+) { + #[inline] + fn eq(&self, other: &($($T,)+)) -> bool { + $(*self.$refN() == *other.$refN())&&+ + } + #[inline] + fn ne(&self, other: &($($T,)+)) -> bool { + $(*self.$refN() != *other.$refN())||+ + } + } + + #[cfg(not(test))] + impl<$($T:TotalEq),+> TotalEq for ($($T,)+) {} + + #[cfg(not(test))] + impl<$($T:Ord + Eq),+> Ord for ($($T,)+) { + #[inline] + fn lt(&self, other: &($($T,)+)) -> bool { + lexical_ord!(lt, $(self.$refN(), other.$refN()),+) + } + #[inline] + fn le(&self, other: &($($T,)+)) -> bool { + lexical_ord!(le, $(self.$refN(), other.$refN()),+) + } + #[inline] + fn ge(&self, other: &($($T,)+)) -> bool { + lexical_ord!(ge, $(self.$refN(), other.$refN()),+) + } + #[inline] + fn gt(&self, other: &($($T,)+)) -> bool { + lexical_ord!(gt, $(self.$refN(), other.$refN()),+) + } + } + + #[cfg(not(test))] + impl<$($T:TotalOrd),+> TotalOrd for ($($T,)+) { + #[inline] + fn cmp(&self, other: &($($T,)+)) -> Ordering { + lexical_cmp!($(self.$refN(), other.$refN()),+) + } + } + + #[cfg(not(test))] + impl<$($T:Default),+> Default for ($($T,)+) { + #[inline] + fn default() -> ($($T,)+) { + ($({ let x: $T = Default::default(); x},)+) + } + } + )+ + } +} + +// Constructs an expression that performs a lexical ordering using method $rel. +// The values are interleaved, so the macro invocation for +// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2, +// a3, b3)` (and similarly for `lexical_cmp`) +macro_rules! lexical_ord { + ($rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { + if *$a != *$b { lexical_ord!($rel, $a, $b) } + else { lexical_ord!($rel, $($rest_a, $rest_b),+) } + }; + ($rel: ident, $a:expr, $b:expr) => { (*$a) . $rel ($b) }; +} + +macro_rules! lexical_cmp { + ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { + match ($a).cmp($b) { + Equal => lexical_cmp!($($rest_a, $rest_b),+), + ordering => ordering + } + }; + ($a:expr, $b:expr) => { ($a).cmp($b) }; +} + +tuple_impls! { + Tuple1 { + (val0, ref0, mut0) -> A { (a) => a } + } + Tuple2 { + (val0, ref0, mut0) -> A { (a, b) => a } + (val1, ref1, mut1) -> B { (a, b) => b } + } + Tuple3 { + (val0, ref0, mut0) -> A { (a, b, c) => a } + (val1, ref1, mut1) -> B { (a, b, c) => b } + (val2, ref2, mut2) -> C { (a, b, c) => c } + } + Tuple4 { + (val0, ref0, mut0) -> A { (a, b, c, d) => a } + (val1, ref1, mut1) -> B { (a, b, c, d) => b } + (val2, ref2, mut2) -> C { (a, b, c, d) => c } + (val3, ref3, mut3) -> D { (a, b, c, d) => d } + } + Tuple5 { + (val0, ref0, mut0) -> A { (a, b, c, d, e) => a } + (val1, ref1, mut1) -> B { (a, b, c, d, e) => b } + (val2, ref2, mut2) -> C { (a, b, c, d, e) => c } + (val3, ref3, mut3) -> D { (a, b, c, d, e) => d } + (val4, ref4, mut4) -> E { (a, b, c, d, e) => e } + } + Tuple6 { + (val0, ref0, mut0) -> A { (a, b, c, d, e, f) => a } + (val1, ref1, mut1) -> B { (a, b, c, d, e, f) => b } + (val2, ref2, mut2) -> C { (a, b, c, d, e, f) => c } + (val3, ref3, mut3) -> D { (a, b, c, d, e, f) => d } + (val4, ref4, mut4) -> E { (a, b, c, d, e, f) => e } + (val5, ref5, mut5) -> F { (a, b, c, d, e, f) => f } + } + Tuple7 { + (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g) => a } + (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g) => b } + (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g) => c } + (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g) => d } + (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g) => e } + (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g) => f } + (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g) => g } + } + Tuple8 { + (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h) => a } + (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h) => b } + (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h) => c } + (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h) => d } + (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h) => e } + (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h) => f } + (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h) => g } + (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h) => h } + } + Tuple9 { + (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i) => a } + (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i) => b } + (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i) => c } + (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i) => d } + (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i) => e } + (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i) => f } + (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i) => g } + (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i) => h } + (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i) => i } + } + Tuple10 { + (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i, j) => a } + (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i, j) => b } + (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i, j) => c } + (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i, j) => d } + (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i, j) => e } + (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i, j) => f } + (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i, j) => g } + (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i, j) => h } + (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i, j) => i } + (val9, ref9, mut9) -> J { (a, b, c, d, e, f, g, h, i, j) => j } + } + Tuple11 { + (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i, j, k) => a } + (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i, j, k) => b } + (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i, j, k) => c } + (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i, j, k) => d } + (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i, j, k) => e } + (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i, j, k) => f } + (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i, j, k) => g } + (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i, j, k) => h } + (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i, j, k) => i } + (val9, ref9, mut9) -> J { (a, b, c, d, e, f, g, h, i, j, k) => j } + (val10, ref10, mut10) -> K { (a, b, c, d, e, f, g, h, i, j, k) => k } + } + Tuple12 { + (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i, j, k, l) => a } + (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i, j, k, l) => b } + (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i, j, k, l) => c } + (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i, j, k, l) => d } + (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i, j, k, l) => e } + (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i, j, k, l) => f } + (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i, j, k, l) => g } + (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i, j, k, l) => h } + (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i, j, k, l) => i } + (val9, ref9, mut9) -> J { (a, b, c, d, e, f, g, h, i, j, k, l) => j } + (val10, ref10, mut10) -> K { (a, b, c, d, e, f, g, h, i, j, k, l) => k } + (val11, ref11, mut11) -> L { (a, b, c, d, e, f, g, h, i, j, k, l) => l } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use clone::Clone; + use cmp::*; + use str::StrSlice; + + #[test] + fn test_clone() { + let a = (1, "2".to_owned()); + let b = a.clone(); + assert_eq!(a, b); + } + + #[test] + fn test_getters() { + macro_rules! test_getter( + ($x:expr, $valN:ident, $refN:ident, $mutN:ident, + $init:expr, $incr:expr, $result:expr) => ({ + assert_eq!($x.$valN(), $init); + assert_eq!(*$x.$refN(), $init); + *$x.$mutN() += $incr; + assert_eq!(*$x.$refN(), $result); + }) + ) + let mut x = (0u8, 1u16, 2u32, 3u64, 4u, 5i8, 6i16, 7i32, 8i64, 9i, 10f32, 11f64); + test_getter!(x, val0, ref0, mut0, 0, 1, 1); + test_getter!(x, val1, ref1, mut1, 1, 1, 2); + test_getter!(x, val2, ref2, mut2, 2, 1, 3); + test_getter!(x, val3, ref3, mut3, 3, 1, 4); + test_getter!(x, val4, ref4, mut4, 4, 1, 5); + test_getter!(x, val5, ref5, mut5, 5, 1, 6); + test_getter!(x, val6, ref6, mut6, 6, 1, 7); + test_getter!(x, val7, ref7, mut7, 7, 1, 8); + test_getter!(x, val8, ref8, mut8, 8, 1, 9); + test_getter!(x, val9, ref9, mut9, 9, 1, 10); + test_getter!(x, val10, ref10, mut10, 10.0, 1.0, 11.0); + test_getter!(x, val11, ref11, mut11, 11.0, 1.0, 12.0); + } + + #[test] + fn test_tuple_cmp() { + let (small, big) = ((1u, 2u, 3u), (3u, 2u, 1u)); + + let nan = 0.0/0.0; + + // Eq + assert_eq!(small, small); + assert_eq!(big, big); + assert!(small != big); + assert!(big != small); + + // Ord + assert!(small < big); + assert!(!(small < small)); + assert!(!(big < small)); + assert!(!(big < big)); + + assert!(small <= small); + assert!(big <= big); + + assert!(big > small); + assert!(small >= small); + assert!(big >= small); + assert!(big >= big); + + assert!(!((1.0, 2.0) < (nan, 3.0))); + assert!(!((1.0, 2.0) <= (nan, 3.0))); + assert!(!((1.0, 2.0) > (nan, 3.0))); + assert!(!((1.0, 2.0) >= (nan, 3.0))); + assert!(((1.0, 2.0) < (2.0, nan))); + assert!(!((2.0, 2.0) < (2.0, nan))); + + // TotalOrd + assert!(small.cmp(&small) == Equal); + assert!(big.cmp(&big) == Equal); + assert!(small.cmp(&big) == Less); + assert!(big.cmp(&small) == Greater); + } + + #[test] + fn test_show() { + assert_eq!(format!("{}", (1,)), "(1,)".to_owned()); + assert_eq!(format!("{}", (1, true)), "(1, true)".to_owned()); + assert_eq!(format!("{}", (1, "hi".to_owned(), true)), "(1, hi, true)".to_owned()); + } +} diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index 7623da8734e..21121449205 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -1242,6 +1242,36 @@ impl Show for *mut T { fn fmt(&self, f: &mut Formatter) -> Result { secret_pointer(self, f) } } +macro_rules! peel(($name:ident, $($other:ident,)*) => (tuple!($($other,)*))) + +macro_rules! tuple ( + () => (); + ( $($name:ident,)+ ) => ( + impl<$($name:Show),*> Show for ($($name,)*) { + #[allow(uppercase_variables, dead_assignment)] + fn fmt(&self, f: &mut Formatter) -> Result { + try!(write!(f.buf, "(")); + let ($(ref $name,)*) = *self; + let mut n = 0; + $( + if n > 0 { + try!(write!(f.buf, ", ")); + } + try!(write!(f.buf, "{}", *$name)); + n += 1; + )* + if n == 1 { + try!(write!(f.buf, ",")); + } + write!(f.buf, ")") + } + } + peel!($($name,)*) + ) +) + +tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } + impl Show for Box { fn fmt(&self, f: &mut Formatter) -> Result { f.pad("Box") } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index aca182a02ea..ac956b11d27 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -147,6 +147,7 @@ pub use core::intrinsics; pub use core::mem; pub use core::ptr; pub use core::raw; +pub use core::tuple; // Run tests with libgreen instead of libnative. // @@ -192,7 +193,6 @@ pub mod prelude; #[path = "num/f64.rs"] pub mod f64; pub mod bool; -pub mod tuple; pub mod slice; pub mod vec; diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs deleted file mode 100644 index cf63ea43fdb..00000000000 --- a/src/libstd/tuple.rs +++ /dev/null @@ -1,350 +0,0 @@ -// 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. - -//! Operations on tuples - -#![allow(missing_doc)] - -use clone::Clone; -#[cfg(not(test))] use cmp::*; -#[cfg(not(test))] use default::Default; -use fmt; -use result::{Ok, Err}; - -// macro for implementing n-ary tuple functions and operations -macro_rules! tuple_impls { - ($( - $Tuple:ident { - $(($valN:ident, $refN:ident, $mutN:ident) -> $T:ident { - ($($x:ident),+) => $ret:expr - })+ - } - )+) => { - $( - pub trait $Tuple<$($T),+> { - $(fn $valN(self) -> $T;)+ - $(fn $refN<'a>(&'a self) -> &'a $T;)+ - $(fn $mutN<'a>(&'a mut self) -> &'a mut $T;)+ - } - - impl<$($T),+> $Tuple<$($T),+> for ($($T,)+) { - $( - #[inline] - #[allow(unused_variable)] - fn $valN(self) -> $T { - let ($($x,)+) = self; $ret - } - - #[inline] - #[allow(unused_variable)] - fn $refN<'a>(&'a self) -> &'a $T { - let ($(ref $x,)+) = *self; $ret - } - - #[inline] - #[allow(unused_variable)] - fn $mutN<'a>(&'a mut self) -> &'a mut $T { - let ($(ref mut $x,)+) = *self; $ret - } - )+ - } - - impl<$($T:Clone),+> Clone for ($($T,)+) { - fn clone(&self) -> ($($T,)+) { - ($(self.$refN().clone(),)+) - } - } - - #[cfg(not(test))] - impl<$($T:Eq),+> Eq for ($($T,)+) { - #[inline] - fn eq(&self, other: &($($T,)+)) -> bool { - $(*self.$refN() == *other.$refN())&&+ - } - #[inline] - fn ne(&self, other: &($($T,)+)) -> bool { - $(*self.$refN() != *other.$refN())||+ - } - } - - #[cfg(not(test))] - impl<$($T:TotalEq),+> TotalEq for ($($T,)+) {} - - #[cfg(not(test))] - impl<$($T:Ord + Eq),+> Ord for ($($T,)+) { - #[inline] - fn lt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(lt, $(self.$refN(), other.$refN()),+) - } - #[inline] - fn le(&self, other: &($($T,)+)) -> bool { - lexical_ord!(le, $(self.$refN(), other.$refN()),+) - } - #[inline] - fn ge(&self, other: &($($T,)+)) -> bool { - lexical_ord!(ge, $(self.$refN(), other.$refN()),+) - } - #[inline] - fn gt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(gt, $(self.$refN(), other.$refN()),+) - } - } - - #[cfg(not(test))] - impl<$($T:TotalOrd),+> TotalOrd for ($($T,)+) { - #[inline] - fn cmp(&self, other: &($($T,)+)) -> Ordering { - lexical_cmp!($(self.$refN(), other.$refN()),+) - } - } - - #[cfg(not(test))] - impl<$($T:Default),+> Default for ($($T,)+) { - #[inline] - fn default() -> ($($T,)+) { - ($({ let x: $T = Default::default(); x},)+) - } - } - - impl<$($T: fmt::Show),+> fmt::Show for ($($T,)+) { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write_tuple!(f.buf, $(self.$refN()),+) - } - } - )+ - } -} - -// Constructs an expression that performs a lexical ordering using method $rel. -// The values are interleaved, so the macro invocation for -// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2, -// a3, b3)` (and similarly for `lexical_cmp`) -macro_rules! lexical_ord { - ($rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { - if *$a != *$b { lexical_ord!($rel, $a, $b) } - else { lexical_ord!($rel, $($rest_a, $rest_b),+) } - }; - ($rel: ident, $a:expr, $b:expr) => { (*$a) . $rel ($b) }; -} - -macro_rules! lexical_cmp { - ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { - match ($a).cmp($b) { - Equal => lexical_cmp!($($rest_a, $rest_b),+), - ordering => ordering - } - }; - ($a:expr, $b:expr) => { ($a).cmp($b) }; -} - -macro_rules! write_tuple { - ($buf:expr, $x:expr) => ( - write!($buf, "({},)", *$x) - ); - ($buf:expr, $hd:expr, $($tl:expr),+) => ({ - try!(write!($buf, "(")); - try!(write!($buf, "{}", *$hd)); - $(try!(write!($buf, ", {}", *$tl));)+ - write!($buf, ")") - }); -} - -tuple_impls! { - Tuple1 { - (val0, ref0, mut0) -> A { (a) => a } - } - Tuple2 { - (val0, ref0, mut0) -> A { (a, b) => a } - (val1, ref1, mut1) -> B { (a, b) => b } - } - Tuple3 { - (val0, ref0, mut0) -> A { (a, b, c) => a } - (val1, ref1, mut1) -> B { (a, b, c) => b } - (val2, ref2, mut2) -> C { (a, b, c) => c } - } - Tuple4 { - (val0, ref0, mut0) -> A { (a, b, c, d) => a } - (val1, ref1, mut1) -> B { (a, b, c, d) => b } - (val2, ref2, mut2) -> C { (a, b, c, d) => c } - (val3, ref3, mut3) -> D { (a, b, c, d) => d } - } - Tuple5 { - (val0, ref0, mut0) -> A { (a, b, c, d, e) => a } - (val1, ref1, mut1) -> B { (a, b, c, d, e) => b } - (val2, ref2, mut2) -> C { (a, b, c, d, e) => c } - (val3, ref3, mut3) -> D { (a, b, c, d, e) => d } - (val4, ref4, mut4) -> E { (a, b, c, d, e) => e } - } - Tuple6 { - (val0, ref0, mut0) -> A { (a, b, c, d, e, f) => a } - (val1, ref1, mut1) -> B { (a, b, c, d, e, f) => b } - (val2, ref2, mut2) -> C { (a, b, c, d, e, f) => c } - (val3, ref3, mut3) -> D { (a, b, c, d, e, f) => d } - (val4, ref4, mut4) -> E { (a, b, c, d, e, f) => e } - (val5, ref5, mut5) -> F { (a, b, c, d, e, f) => f } - } - Tuple7 { - (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g) => a } - (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g) => b } - (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g) => c } - (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g) => d } - (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g) => e } - (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g) => f } - (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g) => g } - } - Tuple8 { - (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h) => a } - (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h) => b } - (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h) => c } - (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h) => d } - (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h) => e } - (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h) => f } - (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h) => g } - (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h) => h } - } - Tuple9 { - (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i) => a } - (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i) => b } - (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i) => c } - (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i) => d } - (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i) => e } - (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i) => f } - (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i) => g } - (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i) => h } - (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i) => i } - } - Tuple10 { - (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i, j) => a } - (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i, j) => b } - (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i, j) => c } - (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i, j) => d } - (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i, j) => e } - (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i, j) => f } - (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i, j) => g } - (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i, j) => h } - (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i, j) => i } - (val9, ref9, mut9) -> J { (a, b, c, d, e, f, g, h, i, j) => j } - } - Tuple11 { - (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i, j, k) => a } - (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i, j, k) => b } - (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i, j, k) => c } - (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i, j, k) => d } - (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i, j, k) => e } - (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i, j, k) => f } - (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i, j, k) => g } - (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i, j, k) => h } - (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i, j, k) => i } - (val9, ref9, mut9) -> J { (a, b, c, d, e, f, g, h, i, j, k) => j } - (val10, ref10, mut10) -> K { (a, b, c, d, e, f, g, h, i, j, k) => k } - } - Tuple12 { - (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i, j, k, l) => a } - (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i, j, k, l) => b } - (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i, j, k, l) => c } - (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i, j, k, l) => d } - (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i, j, k, l) => e } - (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i, j, k, l) => f } - (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i, j, k, l) => g } - (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i, j, k, l) => h } - (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i, j, k, l) => i } - (val9, ref9, mut9) -> J { (a, b, c, d, e, f, g, h, i, j, k, l) => j } - (val10, ref10, mut10) -> K { (a, b, c, d, e, f, g, h, i, j, k, l) => k } - (val11, ref11, mut11) -> L { (a, b, c, d, e, f, g, h, i, j, k, l) => l } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use clone::Clone; - use cmp::*; - use str::StrSlice; - - #[test] - fn test_clone() { - let a = (1, "2".to_owned()); - let b = a.clone(); - assert_eq!(a, b); - } - - #[test] - fn test_getters() { - macro_rules! test_getter( - ($x:expr, $valN:ident, $refN:ident, $mutN:ident, - $init:expr, $incr:expr, $result:expr) => ({ - assert_eq!($x.$valN(), $init); - assert_eq!(*$x.$refN(), $init); - *$x.$mutN() += $incr; - assert_eq!(*$x.$refN(), $result); - }) - ) - let mut x = (0u8, 1u16, 2u32, 3u64, 4u, 5i8, 6i16, 7i32, 8i64, 9i, 10f32, 11f64); - test_getter!(x, val0, ref0, mut0, 0, 1, 1); - test_getter!(x, val1, ref1, mut1, 1, 1, 2); - test_getter!(x, val2, ref2, mut2, 2, 1, 3); - test_getter!(x, val3, ref3, mut3, 3, 1, 4); - test_getter!(x, val4, ref4, mut4, 4, 1, 5); - test_getter!(x, val5, ref5, mut5, 5, 1, 6); - test_getter!(x, val6, ref6, mut6, 6, 1, 7); - test_getter!(x, val7, ref7, mut7, 7, 1, 8); - test_getter!(x, val8, ref8, mut8, 8, 1, 9); - test_getter!(x, val9, ref9, mut9, 9, 1, 10); - test_getter!(x, val10, ref10, mut10, 10.0, 1.0, 11.0); - test_getter!(x, val11, ref11, mut11, 11.0, 1.0, 12.0); - } - - #[test] - fn test_tuple_cmp() { - let (small, big) = ((1u, 2u, 3u), (3u, 2u, 1u)); - - let nan = 0.0/0.0; - - // Eq - assert_eq!(small, small); - assert_eq!(big, big); - assert!(small != big); - assert!(big != small); - - // Ord - assert!(small < big); - assert!(!(small < small)); - assert!(!(big < small)); - assert!(!(big < big)); - - assert!(small <= small); - assert!(big <= big); - - assert!(big > small); - assert!(small >= small); - assert!(big >= small); - assert!(big >= big); - - assert!(!((1.0, 2.0) < (nan, 3.0))); - assert!(!((1.0, 2.0) <= (nan, 3.0))); - assert!(!((1.0, 2.0) > (nan, 3.0))); - assert!(!((1.0, 2.0) >= (nan, 3.0))); - assert!(((1.0, 2.0) < (2.0, nan))); - assert!(!((2.0, 2.0) < (2.0, nan))); - - // TotalOrd - assert!(small.cmp(&small) == Equal); - assert!(big.cmp(&big) == Equal); - assert!(small.cmp(&big) == Less); - assert!(big.cmp(&small) == Greater); - } - - #[test] - fn test_show() { - assert_eq!(format!("{}", (1,)), "(1,)".to_owned()); - assert_eq!(format!("{}", (1, true)), "(1, true)".to_owned()); - assert_eq!(format!("{}", (1, "hi".to_owned(), true)), "(1, hi, true)".to_owned()); - } -} -- cgit 1.4.1-3-g733a5 From 6636215a44b27d1806a2ac646bde1d4ecaa801c4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 21:11:17 -0700 Subject: core: Inherit the bool module --- src/libcore/bool.rs | 273 ++++++++++++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 1 + src/libstd/bool.rs | 302 ------------------------------------------------- src/libstd/from_str.rs | 36 +++++- src/libstd/lib.rs | 3 +- 5 files changed, 310 insertions(+), 305 deletions(-) create mode 100644 src/libcore/bool.rs delete mode 100644 src/libstd/bool.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs new file mode 100644 index 00000000000..0ccb7f93837 --- /dev/null +++ b/src/libcore/bool.rs @@ -0,0 +1,273 @@ +// Copyright 2013 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. + +//! Operations on boolean values (`bool` type) +//! +//! A quick summary: +//! +//! Implementations of the following traits: +//! +//! * `Not` +//! * `Ord` +//! * `TotalOrd` +//! * `Eq` +//! * `Default` +//! * `Zero` +//! +//! A `to_bit` conversion function. + +use num::{Int, one, zero}; + +#[cfg(not(test))] use cmp::{Eq, Ord, TotalOrd, Ordering, TotalEq}; +#[cfg(not(test))] use ops::{Not, BitAnd, BitOr, BitXor}; +#[cfg(not(test))] use default::Default; + +///////////////////////////////////////////////////////////////////////////// +// Freestanding functions +///////////////////////////////////////////////////////////////////////////// + +/// Convert a `bool` to an integer. +/// +/// # Examples +/// +/// ```rust +/// use std::bool; +/// +/// assert_eq!(bool::to_bit::(true), 1u8); +/// assert_eq!(bool::to_bit::(false), 0u8); +/// ``` +#[inline] +pub fn to_bit(p: bool) -> N { + if p { one() } else { zero() } +} + +///////////////////////////////////////////////////////////////////////////// +// Trait impls on `bool` +///////////////////////////////////////////////////////////////////////////// + +#[cfg(not(test))] +impl Not for bool { + /// The logical complement of a boolean value. + /// + /// # Examples + /// + /// ```rust + /// assert_eq!(!true, false); + /// assert_eq!(!false, true); + /// ``` + #[inline] + fn not(&self) -> bool { !*self } +} + +#[cfg(not(test))] +impl BitAnd for bool { + /// Conjunction of two boolean values. + /// + /// # Examples + /// + /// ```rust + /// assert_eq!(false.bitand(&false), false); + /// assert_eq!(true.bitand(&false), false); + /// assert_eq!(false.bitand(&true), false); + /// assert_eq!(true.bitand(&true), true); + /// + /// assert_eq!(false & false, false); + /// assert_eq!(true & false, false); + /// assert_eq!(false & true, false); + /// assert_eq!(true & true, true); + /// ``` + #[inline] + fn bitand(&self, b: &bool) -> bool { *self & *b } +} + +#[cfg(not(test))] +impl BitOr for bool { + /// Disjunction of two boolean values. + /// + /// # Examples + /// + /// ```rust + /// assert_eq!(false.bitor(&false), false); + /// assert_eq!(true.bitor(&false), true); + /// assert_eq!(false.bitor(&true), true); + /// assert_eq!(true.bitor(&true), true); + /// + /// assert_eq!(false | false, false); + /// assert_eq!(true | false, true); + /// assert_eq!(false | true, true); + /// assert_eq!(true | true, true); + /// ``` + #[inline] + fn bitor(&self, b: &bool) -> bool { *self | *b } +} + +#[cfg(not(test))] +impl BitXor for bool { + /// An 'exclusive or' of two boolean values. + /// + /// 'exclusive or' is identical to `or(and(a, not(b)), and(not(a), b))`. + /// + /// # Examples + /// + /// ```rust + /// assert_eq!(false.bitxor(&false), false); + /// assert_eq!(true.bitxor(&false), true); + /// assert_eq!(false.bitxor(&true), true); + /// assert_eq!(true.bitxor(&true), false); + /// + /// assert_eq!(false ^ false, false); + /// assert_eq!(true ^ false, true); + /// assert_eq!(false ^ true, true); + /// assert_eq!(true ^ true, false); + /// ``` + #[inline] + fn bitxor(&self, b: &bool) -> bool { *self ^ *b } +} + +#[cfg(not(test))] +impl Ord for bool { + #[inline] + fn lt(&self, other: &bool) -> bool { + to_bit::(*self) < to_bit(*other) + } +} + +#[cfg(not(test))] +impl TotalOrd for bool { + #[inline] + fn cmp(&self, other: &bool) -> Ordering { + to_bit::(*self).cmp(&to_bit(*other)) + } +} + +/// Equality between two boolean values. +/// +/// Two booleans are equal if they have the same value. +/// +/// # Examples +/// +/// ```rust +/// assert_eq!(false.eq(&true), false); +/// assert_eq!(false == false, true); +/// assert_eq!(false != true, true); +/// assert_eq!(false.ne(&false), false); +/// ``` +#[cfg(not(test))] +impl Eq for bool { + #[inline] + fn eq(&self, other: &bool) -> bool { (*self) == (*other) } +} + +#[cfg(not(test))] +impl TotalEq for bool {} + +#[cfg(not(test))] +impl Default for bool { + fn default() -> bool { false } +} + +#[cfg(test)] +mod tests { + use prelude::*; + use super::to_bit; + use str::StrSlice; + + #[test] + fn test_to_bit() { + assert_eq!(to_bit::(true), 1u8); + assert_eq!(to_bit::(false), 0u8); + } + + #[test] + fn test_eq() { + assert_eq!(false.eq(&true), false); + assert_eq!(false == false, true); + assert_eq!(false != true, true); + assert_eq!(false.ne(&false), false); + } + + #[test] + fn test_bitand() { + assert_eq!(false.bitand(&false), false); + assert_eq!(true.bitand(&false), false); + assert_eq!(false.bitand(&true), false); + assert_eq!(true.bitand(&true), true); + + assert_eq!(false & false, false); + assert_eq!(true & false, false); + assert_eq!(false & true, false); + assert_eq!(true & true, true); + } + + #[test] + fn test_bitor() { + assert_eq!(false.bitor(&false), false); + assert_eq!(true.bitor(&false), true); + assert_eq!(false.bitor(&true), true); + assert_eq!(true.bitor(&true), true); + + assert_eq!(false | false, false); + assert_eq!(true | false, true); + assert_eq!(false | true, true); + assert_eq!(true | true, true); + } + + #[test] + fn test_bitxor() { + assert_eq!(false.bitxor(&false), false); + assert_eq!(true.bitxor(&false), true); + assert_eq!(false.bitxor(&true), true); + assert_eq!(true.bitxor(&true), false); + + assert_eq!(false ^ false, false); + assert_eq!(true ^ false, true); + assert_eq!(false ^ true, true); + assert_eq!(true ^ true, false); + } + + #[test] + fn test_not() { + assert_eq!(!true, false); + assert_eq!(!false, true); + } + + #[test] + fn test_to_str() { + assert_eq!(false.to_str(), "false".to_owned()); + assert_eq!(true.to_str(), "true".to_owned()); + } + + #[test] + fn test_ord() { + assert!(true > false); + assert!(!(false > true)); + + assert!(false < true); + assert!(!(true < false)); + + assert!(false <= false); + assert!(false >= false); + assert!(true <= true); + assert!(true >= true); + + assert!(false <= true); + assert!(!(false >= true)); + assert!(true >= false); + assert!(!(true <= false)); + } + + #[test] + fn test_totalord() { + assert!(true.cmp(&true) == Equal); + assert!(false.cmp(&false) == Equal); + assert!(true.cmp(&false) == Greater); + assert!(false.cmp(&true) == Less); + } +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 19f64c6d067..666e5b813c9 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -41,6 +41,7 @@ pub mod container; mod unit; pub mod any; +pub mod bool; pub mod finally; pub mod raw; pub mod char; diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs deleted file mode 100644 index 5a07c860b5d..00000000000 --- a/src/libstd/bool.rs +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright 2013 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. - -//! Operations on boolean values (`bool` type) -//! -//! A quick summary: -//! -//! Implementations of the following traits: -//! -//! * `FromStr` -//! * `Not` -//! * `Ord` -//! * `TotalOrd` -//! * `Eq` -//! * `Default` -//! * `Zero` -//! -//! A `to_bit` conversion function. - -use from_str::FromStr; -use num::{Int, one, zero}; -use option::{None, Option, Some}; - -#[cfg(not(test))] use cmp::{Eq, Ord, TotalOrd, Ordering}; -#[cfg(not(test))] use ops::{Not, BitAnd, BitOr, BitXor}; -#[cfg(not(test))] use default::Default; - -///////////////////////////////////////////////////////////////////////////// -// Freestanding functions -///////////////////////////////////////////////////////////////////////////// - -/// Convert a `bool` to an integer. -/// -/// # Examples -/// -/// ```rust -/// use std::bool; -/// -/// assert_eq!(bool::to_bit::(true), 1u8); -/// assert_eq!(bool::to_bit::(false), 0u8); -/// ``` -#[inline] -pub fn to_bit(p: bool) -> N { - if p { one() } else { zero() } -} - -///////////////////////////////////////////////////////////////////////////// -// Trait impls on `bool` -///////////////////////////////////////////////////////////////////////////// - -impl FromStr for bool { - /// Parse a `bool` from a string. - /// - /// Yields an `Option`, because `s` may or may not actually be parseable. - /// - /// # Examples - /// - /// ```rust - /// assert_eq!(from_str::("true"), Some(true)); - /// assert_eq!(from_str::("false"), Some(false)); - /// assert_eq!(from_str::("not even a boolean"), None); - /// ``` - #[inline] - fn from_str(s: &str) -> Option { - match s { - "true" => Some(true), - "false" => Some(false), - _ => None, - } - } -} - -#[cfg(not(test))] -impl Not for bool { - /// The logical complement of a boolean value. - /// - /// # Examples - /// - /// ```rust - /// assert_eq!(!true, false); - /// assert_eq!(!false, true); - /// ``` - #[inline] - fn not(&self) -> bool { !*self } -} - -#[cfg(not(test))] -impl BitAnd for bool { - /// Conjunction of two boolean values. - /// - /// # Examples - /// - /// ```rust - /// assert_eq!(false.bitand(&false), false); - /// assert_eq!(true.bitand(&false), false); - /// assert_eq!(false.bitand(&true), false); - /// assert_eq!(true.bitand(&true), true); - /// - /// assert_eq!(false & false, false); - /// assert_eq!(true & false, false); - /// assert_eq!(false & true, false); - /// assert_eq!(true & true, true); - /// ``` - #[inline] - fn bitand(&self, b: &bool) -> bool { *self & *b } -} - -#[cfg(not(test))] -impl BitOr for bool { - /// Disjunction of two boolean values. - /// - /// # Examples - /// - /// ```rust - /// assert_eq!(false.bitor(&false), false); - /// assert_eq!(true.bitor(&false), true); - /// assert_eq!(false.bitor(&true), true); - /// assert_eq!(true.bitor(&true), true); - /// - /// assert_eq!(false | false, false); - /// assert_eq!(true | false, true); - /// assert_eq!(false | true, true); - /// assert_eq!(true | true, true); - /// ``` - #[inline] - fn bitor(&self, b: &bool) -> bool { *self | *b } -} - -#[cfg(not(test))] -impl BitXor for bool { - /// An 'exclusive or' of two boolean values. - /// - /// 'exclusive or' is identical to `or(and(a, not(b)), and(not(a), b))`. - /// - /// # Examples - /// - /// ```rust - /// assert_eq!(false.bitxor(&false), false); - /// assert_eq!(true.bitxor(&false), true); - /// assert_eq!(false.bitxor(&true), true); - /// assert_eq!(true.bitxor(&true), false); - /// - /// assert_eq!(false ^ false, false); - /// assert_eq!(true ^ false, true); - /// assert_eq!(false ^ true, true); - /// assert_eq!(true ^ true, false); - /// ``` - #[inline] - fn bitxor(&self, b: &bool) -> bool { *self ^ *b } -} - -#[cfg(not(test))] -impl Ord for bool { - #[inline] - fn lt(&self, other: &bool) -> bool { - to_bit::(*self) < to_bit(*other) - } -} - -#[cfg(not(test))] -impl TotalOrd for bool { - #[inline] - fn cmp(&self, other: &bool) -> Ordering { - to_bit::(*self).cmp(&to_bit(*other)) - } -} - -/// Equality between two boolean values. -/// -/// Two booleans are equal if they have the same value. -/// -/// # Examples -/// -/// ```rust -/// assert_eq!(false.eq(&true), false); -/// assert_eq!(false == false, true); -/// assert_eq!(false != true, true); -/// assert_eq!(false.ne(&false), false); -/// ``` -#[cfg(not(test))] -impl Eq for bool { - #[inline] - fn eq(&self, other: &bool) -> bool { (*self) == (*other) } -} - -#[cfg(not(test))] -impl Default for bool { - fn default() -> bool { false } -} - -#[cfg(test)] -mod tests { - use prelude::*; - use super::to_bit; - use str::StrSlice; - - #[test] - fn test_to_bit() { - assert_eq!(to_bit::(true), 1u8); - assert_eq!(to_bit::(false), 0u8); - } - - #[test] - fn test_eq() { - assert_eq!(false.eq(&true), false); - assert_eq!(false == false, true); - assert_eq!(false != true, true); - assert_eq!(false.ne(&false), false); - } - - #[test] - fn test_bitand() { - assert_eq!(false.bitand(&false), false); - assert_eq!(true.bitand(&false), false); - assert_eq!(false.bitand(&true), false); - assert_eq!(true.bitand(&true), true); - - assert_eq!(false & false, false); - assert_eq!(true & false, false); - assert_eq!(false & true, false); - assert_eq!(true & true, true); - } - - #[test] - fn test_bitor() { - assert_eq!(false.bitor(&false), false); - assert_eq!(true.bitor(&false), true); - assert_eq!(false.bitor(&true), true); - assert_eq!(true.bitor(&true), true); - - assert_eq!(false | false, false); - assert_eq!(true | false, true); - assert_eq!(false | true, true); - assert_eq!(true | true, true); - } - - #[test] - fn test_bitxor() { - assert_eq!(false.bitxor(&false), false); - assert_eq!(true.bitxor(&false), true); - assert_eq!(false.bitxor(&true), true); - assert_eq!(true.bitxor(&true), false); - - assert_eq!(false ^ false, false); - assert_eq!(true ^ false, true); - assert_eq!(false ^ true, true); - assert_eq!(true ^ true, false); - } - - #[test] - fn test_not() { - assert_eq!(!true, false); - assert_eq!(!false, true); - } - - #[test] - fn test_from_str() { - assert_eq!(from_str::("true"), Some(true)); - assert_eq!(from_str::("false"), Some(false)); - assert_eq!(from_str::("not even a boolean"), None); - } - - #[test] - fn test_to_str() { - assert_eq!(false.to_str(), "false".to_owned()); - assert_eq!(true.to_str(), "true".to_owned()); - } - - #[test] - fn test_ord() { - assert!(true > false); - assert!(!(false > true)); - - assert!(false < true); - assert!(!(true < false)); - - assert!(false <= false); - assert!(false >= false); - assert!(true <= true); - assert!(true >= true); - - assert!(false <= true); - assert!(!(false >= true)); - assert!(true >= false); - assert!(!(true <= false)); - } - - #[test] - fn test_totalord() { - assert!(true.cmp(&true) == Equal); - assert!(false.cmp(&false) == Equal); - assert!(true.cmp(&false) == Greater); - assert!(false.cmp(&true) == Less); - } -} diff --git a/src/libstd/from_str.rs b/src/libstd/from_str.rs index 289a5f11c4f..62bb8e4d969 100644 --- a/src/libstd/from_str.rs +++ b/src/libstd/from_str.rs @@ -10,7 +10,7 @@ //! The `FromStr` trait for types that can be created from strings -use option::Option; +use option::{Option, Some, None}; /// A trait to abstract the idea of creating a new instance of a type from a /// string. @@ -24,3 +24,37 @@ pub trait FromStr { pub fn from_str(s: &str) -> Option { FromStr::from_str(s) } + +impl FromStr for bool { + /// Parse a `bool` from a string. + /// + /// Yields an `Option`, because `s` may or may not actually be parseable. + /// + /// # Examples + /// + /// ```rust + /// assert_eq!(from_str::("true"), Some(true)); + /// assert_eq!(from_str::("false"), Some(false)); + /// assert_eq!(from_str::("not even a boolean"), None); + /// ``` + #[inline] + fn from_str(s: &str) -> Option { + match s { + "true" => Some(true), + "false" => Some(false), + _ => None, + } + } +} + +#[cfg(test)] +mod test { + use prelude::*; + + #[test] + fn test_bool_from_str() { + assert_eq!(from_str::("true"), Some(true)); + assert_eq!(from_str::("false"), Some(false)); + assert_eq!(from_str::("not even a boolean"), None); + } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ac956b11d27..9e74a291eef 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -138,6 +138,7 @@ extern crate core; #[cfg(not(test))] pub use ty = core::ty; pub use core::any; +pub use core::bool; pub use core::cast; pub use core::char; pub use core::clone; @@ -192,8 +193,6 @@ pub mod prelude; #[path = "num/f32.rs"] pub mod f32; #[path = "num/f64.rs"] pub mod f64; -pub mod bool; - pub mod slice; pub mod vec; pub mod str; -- cgit 1.4.1-3-g733a5 From 06fcb6b1c81f1f5190d431c169cd0c725fecf18e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 21:35:56 -0700 Subject: core: Inherit the option module --- src/libcore/lib.rs | 1 + src/libcore/option.rs | 881 +++++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/fmt/mod.rs | 9 + src/libstd/lib.rs | 2 +- src/libstd/option.rs | 882 -------------------------------------------------- 5 files changed, 892 insertions(+), 883 deletions(-) create mode 100644 src/libcore/option.rs delete mode 100644 src/libstd/option.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 666e5b813c9..2a845f32a7e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -43,6 +43,7 @@ mod unit; pub mod any; pub mod bool; pub mod finally; +pub mod option; pub mod raw; pub mod char; pub mod tuple; diff --git a/src/libcore/option.rs b/src/libcore/option.rs new file mode 100644 index 00000000000..31a452553e5 --- /dev/null +++ b/src/libcore/option.rs @@ -0,0 +1,881 @@ +// 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. + +//! Optional values +//! +//! Type `Option` represents an optional value: every `Option` +//! is either `Some` and contains a value, or `None`, and +//! does not. `Option` types are very common in Rust code, as +//! they have a number of uses: +//! +//! * Initial values +//! * Return values for functions that are not defined +//! over their entire input range (partial functions) +//! * Return value for otherwise reporting simple errors, where `None` is +//! returned on error +//! * Optional struct fields +//! * Struct fields that can be loaned or "taken" +//! * Optional function arguments +//! * Nullable pointers +//! * Swapping things out of difficult situations +//! +//! Options are commonly paired with pattern matching to query the presence +//! of a value and take action, always accounting for the `None` case. +//! +//! ``` +//! # // FIXME This is not the greatest first example +//! // cow_says contains the word "moo" +//! let cow_says = Some("moo"); +//! // dog_says does not contain a value +//! let dog_says: Option<&str> = None; +//! +//! // Pattern match to retrieve the value +//! match (cow_says, dog_says) { +//! (Some(cow_words), Some(dog_words)) => { +//! println!("Cow says {} and dog says {}!", cow_words, dog_words); +//! } +//! (Some(cow_words), None) => println!("Cow says {}", cow_words), +//! (None, Some(dog_words)) => println!("Dog says {}", dog_words), +//! (None, None) => println!("Cow and dog are suspiciously silent") +//! } +//! ``` +//! +// +// FIXME: Show how `Option` is used in practice, with lots of methods +// +//! # Options and pointers ("nullable" pointers) +//! +//! Rust's pointer types must always point to a valid location; there are +//! no "null" pointers. Instead, Rust has *optional* pointers, like +//! the optional owned box, `Option>`. +//! +//! The following example uses `Option` to create an optional box of +//! `int`. Notice that in order to use the inner `int` value first the +//! `check_optional` function needs to use pattern matching to +//! determine whether the box has a value (i.e. it is `Some(...)`) or +//! not (`None`). +//! +//! ``` +//! let optional: Option> = None; +//! check_optional(&optional); +//! +//! let optional: Option> = Some(box 9000); +//! check_optional(&optional); +//! +//! fn check_optional(optional: &Option>) { +//! match *optional { +//! Some(ref p) => println!("have value {}", p), +//! None => println!("have no value") +//! } +//! } +//! ``` +//! +//! This usage of `Option` to create safe nullable pointers is so +//! common that Rust does special optimizations to make the +//! representation of `Option>` a single pointer. Optional pointers +//! in Rust are stored as efficiently as any other pointer type. +//! +//! # Examples +//! +//! Basic pattern matching on `Option`: +//! +//! ``` +//! let msg = Some("howdy"); +//! +//! // Take a reference to the contained string +//! match msg { +//! Some(ref m) => println!("{}", *m), +//! None => () +//! } +//! +//! // Remove the contained string, destroying the Option +//! let unwrapped_msg = match msg { +//! Some(m) => m, +//! None => "default message" +//! }; +//! ``` +//! +//! Initialize a result to `None` before a loop: +//! +//! ``` +//! enum Kingdom { Plant(uint, &'static str), Animal(uint, &'static str) } +//! +//! // A list of data to search through. +//! let all_the_big_things = [ +//! Plant(250, "redwood"), +//! Plant(230, "noble fir"), +//! Plant(229, "sugar pine"), +//! Animal(25, "blue whale"), +//! Animal(19, "fin whale"), +//! Animal(15, "north pacific right whale"), +//! ]; +//! +//! // We're going to search for the name of the biggest animal, +//! // but to start with we've just got `None`. +//! let mut name_of_biggest_animal = None; +//! let mut size_of_biggest_animal = 0; +//! for big_thing in all_the_big_things.iter() { +//! match *big_thing { +//! Animal(size, name) if size > size_of_biggest_animal => { +//! // Now we've found the name of some big animal +//! size_of_biggest_animal = size; +//! name_of_biggest_animal = Some(name); +//! } +//! Animal(..) | Plant(..) => () +//! } +//! } +//! +//! match name_of_biggest_animal { +//! Some(name) => println!("the biggest animal is {}", name), +//! None => println!("there are no animals :(") +//! } +//! ``` + +use any::Any; +use cmp::{Eq, TotalEq, TotalOrd}; +use default::Default; +use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSize}; +use kinds::Send; +use mem; +use slice; + +/// The `Option` +#[deriving(Clone, Eq, Ord, TotalEq, TotalOrd)] +pub enum Option { + /// No value + None, + /// Some value `T` + Some(T) +} + +///////////////////////////////////////////////////////////////////////////// +// Type implementation +///////////////////////////////////////////////////////////////////////////// + +impl Option { + ///////////////////////////////////////////////////////////////////////// + // Querying the contained values + ///////////////////////////////////////////////////////////////////////// + + /// Returns `true` if the option is a `Some` value + #[inline] + pub fn is_some(&self) -> bool { + match *self { + Some(_) => true, + None => false + } + } + + /// Returns `true` if the option is a `None` value + #[inline] + pub fn is_none(&self) -> bool { + !self.is_some() + } + + ///////////////////////////////////////////////////////////////////////// + // Adapter for working with references + ///////////////////////////////////////////////////////////////////////// + + /// Convert from `Option` to `Option<&T>` + /// + /// # Example + /// + /// Convert an `Option<~str>` into an `Option`, preserving the original. + /// The `map` method takes the `self` argument by value, consuming the original, + /// so this technique uses `as_ref` to first take an `Option` to a reference + /// to the value inside the original. + /// + /// ``` + /// let num_as_str: Option<~str> = Some("10".to_owned()); + /// // First, cast `Option<~str>` to `Option<&~str>` with `as_ref`, + /// // then consume *that* with `map`, leaving `num_as_str` on the stack. + /// let num_as_int: Option = num_as_str.as_ref().map(|n| n.len()); + /// println!("still can print num_as_str: {}", num_as_str); + /// ``` + #[inline] + pub fn as_ref<'r>(&'r self) -> Option<&'r T> { + match *self { Some(ref x) => Some(x), None => None } + } + + /// Convert from `Option` to `Option<&mut T>` + #[inline] + pub fn as_mut<'r>(&'r mut self) -> Option<&'r mut T> { + match *self { Some(ref mut x) => Some(x), None => None } + } + + /// Convert from `Option` to `&[T]` (without copying) + #[inline] + pub fn as_slice<'r>(&'r self) -> &'r [T] { + match *self { + Some(ref x) => slice::ref_slice(x), + None => &[] + } + } + + /// Convert from `Option` to `&mut [T]` (without copying) + #[inline] + pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [T] { + match *self { + Some(ref mut x) => slice::mut_ref_slice(x), + None => &mut [] + } + } + + ///////////////////////////////////////////////////////////////////////// + // Getting to contained values + ///////////////////////////////////////////////////////////////////////// + + /// Unwraps an option, yielding the content of a `Some` + /// + /// # Failure + /// + /// Fails if the value is a `None` with a custom failure message provided by `msg`. + #[inline] + pub fn expect(self, msg: M) -> T { + match self { + Some(val) => val, + None => fail!(msg), + } + } + + /// Moves a value out of an option type and returns it, consuming the `Option`. + /// + /// # Failure + /// + /// Fails if the self value equals `None`. + /// + /// # Safety note + /// + /// In general, because this function may fail, its use is discouraged. + /// Instead, prefer to use pattern matching and handle the `None` + /// case explicitly. + #[inline] + pub fn unwrap(self) -> T { + match self { + Some(val) => val, + None => fail!("called `Option::unwrap()` on a `None` value"), + } + } + + /// Returns the contained value or a default. + #[inline] + pub fn unwrap_or(self, def: T) -> T { + match self { + Some(x) => x, + None => def + } + } + + /// Returns the contained value or computes it from a closure. + #[inline] + pub fn unwrap_or_else(self, f: || -> T) -> T { + match self { + Some(x) => x, + None => f() + } + } + + ///////////////////////////////////////////////////////////////////////// + // Transforming contained values + ///////////////////////////////////////////////////////////////////////// + + /// Maps an `Option` to `Option` by applying a function to a contained value + /// + /// # Example + /// + /// Convert an `Option<~str>` into an `Option`, consuming the original: + /// + /// ``` + /// let num_as_str: Option<~str> = Some("10".to_owned()); + /// // `Option::map` takes self *by value*, consuming `num_as_str` + /// let num_as_int: Option = num_as_str.map(|n| n.len()); + /// ``` + #[inline] + pub fn map(self, f: |T| -> U) -> Option { + match self { Some(x) => Some(f(x)), None => None } + } + + /// Applies a function to the contained value or returns a default. + #[inline] + pub fn map_or(self, def: U, f: |T| -> U) -> U { + match self { None => def, Some(t) => f(t) } + } + + /// Applies a function to the contained value or does nothing. + /// Returns true if the contained value was mutated. + pub fn mutate(&mut self, f: |T| -> T) -> bool { + if self.is_some() { + *self = Some(f(self.take_unwrap())); + true + } else { false } + } + + /// Applies a function to the contained value or sets it to a default. + /// Returns true if the contained value was mutated, or false if set to the default. + pub fn mutate_or_set(&mut self, def: T, f: |T| -> T) -> bool { + if self.is_some() { + *self = Some(f(self.take_unwrap())); + true + } else { + *self = Some(def); + false + } + } + + ///////////////////////////////////////////////////////////////////////// + // Iterator constructors + ///////////////////////////////////////////////////////////////////////// + + /// Returns an iterator over the possibly contained value. + #[inline] + pub fn iter<'r>(&'r self) -> Item<&'r T> { + Item{opt: self.as_ref()} + } + + /// Returns a mutable iterator over the possibly contained value. + #[inline] + pub fn mut_iter<'r>(&'r mut self) -> Item<&'r mut T> { + Item{opt: self.as_mut()} + } + + /// Returns a consuming iterator over the possibly contained value. + #[inline] + pub fn move_iter(self) -> Item { + Item{opt: self} + } + + ///////////////////////////////////////////////////////////////////////// + // Boolean operations on the values, eager and lazy + ///////////////////////////////////////////////////////////////////////// + + /// Returns `None` if the option is `None`, otherwise returns `optb`. + #[inline] + pub fn and(self, optb: Option) -> Option { + match self { + Some(_) => optb, + None => None, + } + } + + /// Returns `None` if the option is `None`, otherwise calls `f` with the + /// wrapped value and returns the result. + #[inline] + pub fn and_then(self, f: |T| -> Option) -> Option { + match self { + Some(x) => f(x), + None => None, + } + } + + /// Returns the option if it contains a value, otherwise returns `optb`. + #[inline] + pub fn or(self, optb: Option) -> Option { + match self { + Some(_) => self, + None => optb + } + } + + /// Returns the option if it contains a value, otherwise calls `f` and + /// returns the result. + #[inline] + pub fn or_else(self, f: || -> Option) -> Option { + match self { + Some(_) => self, + None => f() + } + } + + ///////////////////////////////////////////////////////////////////////// + // Misc + ///////////////////////////////////////////////////////////////////////// + + /// Takes the value out of the option, leaving a `None` in its place. + #[inline] + pub fn take(&mut self) -> Option { + mem::replace(self, None) + } + + /// Filters an optional value using a given function. + #[inline(always)] + pub fn filtered(self, f: |t: &T| -> bool) -> Option { + match self { + Some(x) => if f(&x) { Some(x) } else { None }, + None => None + } + } + + /// Applies a function zero or more times until the result is `None`. + #[inline] + pub fn while_some(self, f: |v: T| -> Option) { + let mut opt = self; + loop { + match opt { + Some(x) => opt = f(x), + None => break + } + } + } + + ///////////////////////////////////////////////////////////////////////// + // Common special cases + ///////////////////////////////////////////////////////////////////////// + + /// The option dance. Moves a value out of an option type and returns it, + /// replacing the original with `None`. + /// + /// # Failure + /// + /// Fails if the value equals `None`. + #[inline] + pub fn take_unwrap(&mut self) -> T { + match self.take() { + Some(x) => x, + None => fail!("called `Option::take_unwrap()` on a `None` value") + } + } + + /// Gets an immutable reference to the value inside an option. + /// + /// # Failure + /// + /// Fails if the value equals `None` + /// + /// # Safety note + /// + /// In general, because this function may fail, its use is discouraged + /// (calling `get` on `None` is akin to dereferencing a null pointer). + /// Instead, prefer to use pattern matching and handle the `None` + /// case explicitly. + #[inline] + pub fn get_ref<'a>(&'a self) -> &'a T { + match *self { + Some(ref x) => x, + None => fail!("called `Option::get_ref()` on a `None` value"), + } + } + + /// Gets a mutable reference to the value inside an option. + /// + /// # Failure + /// + /// Fails if the value equals `None` + /// + /// # Safety note + /// + /// In general, because this function may fail, its use is discouraged + /// (calling `get` on `None` is akin to dereferencing a null pointer). + /// Instead, prefer to use pattern matching and handle the `None` + /// case explicitly. + #[inline] + pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T { + match *self { + Some(ref mut x) => x, + None => fail!("called `Option::get_mut_ref()` on a `None` value"), + } + } +} + +impl Option { + /// Returns the contained value or a default + /// + /// Consumes the `self` argument then, if `Some`, returns the contained + /// value, otherwise if `None`, returns the default value for that + /// type. + /// + /// # Example + /// + /// Convert a string to an integer, turning poorly-formed strings + /// into 0 (the default value for integers). `from_str` converts + /// a string to any other type that implements `FromStr`, returning + /// `None` on error. + /// + /// ``` + /// let good_year_from_input = "1909"; + /// let bad_year_from_input = "190blarg"; + /// let good_year = from_str(good_year_from_input).unwrap_or_default(); + /// let bad_year = from_str(bad_year_from_input).unwrap_or_default(); + /// + /// assert_eq!(1909, good_year); + /// assert_eq!(0, bad_year); + /// ``` + #[inline] + pub fn unwrap_or_default(self) -> T { + match self { + Some(x) => x, + None => Default::default() + } + } +} + +///////////////////////////////////////////////////////////////////////////// +// Trait implementations +///////////////////////////////////////////////////////////////////////////// + +impl Default for Option { + #[inline] + fn default() -> Option { None } +} + +///////////////////////////////////////////////////////////////////////////// +// The Option Iterator +///////////////////////////////////////////////////////////////////////////// + +/// An `Option` iterator that yields either one or zero elements +/// +/// The `Item` iterator is returned by the `iter`, `mut_iter` and `move_iter` +/// methods on `Option`. +#[deriving(Clone)] +pub struct Item { + opt: Option +} + +impl Iterator for Item { + #[inline] + fn next(&mut self) -> Option { + self.opt.take() + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + match self.opt { + Some(_) => (1, Some(1)), + None => (0, Some(0)), + } + } +} + +impl DoubleEndedIterator for Item { + #[inline] + fn next_back(&mut self) -> Option { + self.opt.take() + } +} + +impl ExactSize for Item {} + +///////////////////////////////////////////////////////////////////////////// +// Free functions +///////////////////////////////////////////////////////////////////////////// + +/// Takes each element in the `Iterator`: if it is `None`, no further +/// elements are taken, and the `None` is returned. Should no `None` occur, a +/// vector containing the values of each `Option` is returned. +/// +/// Here is an example which increments every integer in a vector, +/// checking for overflow: +/// +/// fn inc_conditionally(x: uint) -> Option { +/// if x == uint::MAX { return None; } +/// else { return Some(x+1u); } +/// } +/// let v = [1u, 2, 3]; +/// let res = collect(v.iter().map(|&x| inc_conditionally(x))); +/// assert!(res == Some(~[2u, 3, 4])); +#[inline] +pub fn collect>, V: FromIterator>(iter: Iter) -> Option { + // FIXME(#11084): This should be twice as fast once this bug is closed. + let mut iter = iter.scan(false, |state, x| { + match x { + Some(x) => Some(x), + None => { + *state = true; + None + } + } + }); + + let v: V = FromIterator::from_iter(iter.by_ref()); + + if iter.state { + None + } else { + Some(v) + } +} + +///////////////////////////////////////////////////////////////////////////// +// Tests +///////////////////////////////////////////////////////////////////////////// + +#[cfg(test)] +mod tests { + use super::*; + use prelude::*; + + use iter::range; + use str::StrSlice; + use kinds::marker; + use slice::ImmutableVector; + + #[test] + fn test_get_ptr() { + unsafe { + let x = box 0; + let addr_x: *int = ::cast::transmute(&*x); + let opt = Some(x); + let y = opt.unwrap(); + let addr_y: *int = ::cast::transmute(&*y); + assert_eq!(addr_x, addr_y); + } + } + + #[test] + fn test_get_str() { + let x = "test".to_owned(); + let addr_x = x.as_ptr(); + let opt = Some(x); + let y = opt.unwrap(); + let addr_y = y.as_ptr(); + assert_eq!(addr_x, addr_y); + } + + #[test] + fn test_get_resource() { + use rc::Rc; + use cell::RefCell; + + struct R { + i: Rc>, + } + + #[unsafe_destructor] + impl ::ops::Drop for R { + fn drop(&mut self) { + let ii = &*self.i; + let i = ii.borrow().clone(); + *ii.borrow_mut() = i + 1; + } + } + + fn R(i: Rc>) -> R { + R { + i: i + } + } + + let i = Rc::new(RefCell::new(0)); + { + let x = R(i.clone()); + let opt = Some(x); + let _y = opt.unwrap(); + } + assert_eq!(*i.borrow(), 1); + } + + #[test] + fn test_option_dance() { + let x = Some(()); + let mut y = Some(5); + let mut y2 = 0; + for _x in x.iter() { + y2 = y.take_unwrap(); + } + assert_eq!(y2, 5); + assert!(y.is_none()); + } + + #[test] #[should_fail] + fn test_option_too_much_dance() { + let mut y = Some(marker::NoCopy); + let _y2 = y.take_unwrap(); + let _y3 = y.take_unwrap(); + } + + #[test] + fn test_and() { + let x: Option = Some(1); + assert_eq!(x.and(Some(2)), Some(2)); + assert_eq!(x.and(None::), None); + + let x: Option = None; + assert_eq!(x.and(Some(2)), None); + assert_eq!(x.and(None::), None); + } + + #[test] + fn test_and_then() { + let x: Option = Some(1); + assert_eq!(x.and_then(|x| Some(x + 1)), Some(2)); + assert_eq!(x.and_then(|_| None::), None); + + let x: Option = None; + assert_eq!(x.and_then(|x| Some(x + 1)), None); + assert_eq!(x.and_then(|_| None::), None); + } + + #[test] + fn test_or() { + let x: Option = Some(1); + assert_eq!(x.or(Some(2)), Some(1)); + assert_eq!(x.or(None), Some(1)); + + let x: Option = None; + assert_eq!(x.or(Some(2)), Some(2)); + assert_eq!(x.or(None), None); + } + + #[test] + fn test_or_else() { + let x: Option = Some(1); + assert_eq!(x.or_else(|| Some(2)), Some(1)); + assert_eq!(x.or_else(|| None), Some(1)); + + let x: Option = None; + assert_eq!(x.or_else(|| Some(2)), Some(2)); + assert_eq!(x.or_else(|| None), None); + } + + #[test] + fn test_option_while_some() { + let mut i = 0; + Some(10).while_some(|j| { + i += 1; + if j > 0 { + Some(j-1) + } else { + None + } + }); + assert_eq!(i, 11); + } + + #[test] + fn test_unwrap() { + assert_eq!(Some(1).unwrap(), 1); + assert_eq!(Some("hello".to_owned()).unwrap(), "hello".to_owned()); + } + + #[test] + #[should_fail] + fn test_unwrap_fail1() { + let x: Option = None; + x.unwrap(); + } + + #[test] + #[should_fail] + fn test_unwrap_fail2() { + let x: Option<~str> = None; + x.unwrap(); + } + + #[test] + fn test_unwrap_or() { + let x: Option = Some(1); + assert_eq!(x.unwrap_or(2), 1); + + let x: Option = None; + assert_eq!(x.unwrap_or(2), 2); + } + + #[test] + fn test_unwrap_or_else() { + let x: Option = Some(1); + assert_eq!(x.unwrap_or_else(|| 2), 1); + + let x: Option = None; + assert_eq!(x.unwrap_or_else(|| 2), 2); + } + + #[test] + fn test_filtered() { + let some_stuff = Some(42); + let modified_stuff = some_stuff.filtered(|&x| {x < 10}); + assert_eq!(some_stuff.unwrap(), 42); + assert!(modified_stuff.is_none()); + } + + #[test] + fn test_iter() { + let val = 5; + + let x = Some(val); + let mut it = x.iter(); + + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next(), Some(&val)); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); + } + + #[test] + fn test_mut_iter() { + let val = 5; + let new_val = 11; + + let mut x = Some(val); + { + let mut it = x.mut_iter(); + + assert_eq!(it.size_hint(), (1, Some(1))); + + match it.next() { + Some(interior) => { + assert_eq!(*interior, val); + *interior = new_val; + } + None => assert!(false), + } + + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); + } + assert_eq!(x, Some(new_val)); + } + + #[test] + fn test_ord() { + let small = Some(1.0); + let big = Some(5.0); + let nan = Some(0.0/0.0); + assert!(!(nan < big)); + assert!(!(nan > big)); + assert!(small < big); + assert!(None < big); + assert!(big > None); + } + + #[test] + fn test_mutate() { + let mut x = Some(3i); + assert!(x.mutate(|i| i+1)); + assert_eq!(x, Some(4i)); + assert!(x.mutate_or_set(0, |i| i+1)); + assert_eq!(x, Some(5i)); + x = None; + assert!(!x.mutate(|i| i+1)); + assert_eq!(x, None); + assert!(!x.mutate_or_set(0i, |i| i+1)); + assert_eq!(x, Some(0i)); + } + + #[test] + fn test_collect() { + let v: Option<~[int]> = collect(range(0, 0) + .map(|_| Some(0))); + assert_eq!(v, Some(box [])); + + let v: Option<~[int]> = collect(range(0, 3) + .map(|x| Some(x))); + assert_eq!(v, Some(box [0, 1, 2])); + + let v: Option<~[int]> = collect(range(0, 3) + .map(|x| if x > 1 { None } else { Some(x) })); + assert_eq!(v, None); + + // test that it does not take more elements than it needs + let mut functions = [|| Some(()), || None, || fail!()]; + + let v: Option<~[()]> = collect(functions.mut_iter().map(|f| (*f)())); + + assert_eq!(v, None); + } +} diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index 21121449205..a20f0392771 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -1280,6 +1280,15 @@ impl<'a> Show for &'a any::Any { fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") } } +impl Show for Option { + fn fmt(&self, f: &mut Formatter) -> Result { + match *self { + Some(ref t) => write!(f.buf, "Some({})", *t), + None => write!(f.buf, "None"), + } + } +} + impl Show for () { fn fmt(&self, f: &mut Formatter) -> Result { f.pad("()") diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 9e74a291eef..64eff2c4762 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -146,6 +146,7 @@ pub use core::container; pub use core::default; pub use core::intrinsics; pub use core::mem; +pub use core::option; pub use core::ptr; pub use core::raw; pub use core::tuple; @@ -222,7 +223,6 @@ pub mod hash; /* Common data structures */ -pub mod option; pub mod result; pub mod cell; diff --git a/src/libstd/option.rs b/src/libstd/option.rs deleted file mode 100644 index fa7b5c94857..00000000000 --- a/src/libstd/option.rs +++ /dev/null @@ -1,882 +0,0 @@ -// 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. - -//! Optional values -//! -//! Type `Option` represents an optional value: every `Option` -//! is either `Some` and contains a value, or `None`, and -//! does not. `Option` types are very common in Rust code, as -//! they have a number of uses: -//! -//! * Initial values -//! * Return values for functions that are not defined -//! over their entire input range (partial functions) -//! * Return value for otherwise reporting simple errors, where `None` is -//! returned on error -//! * Optional struct fields -//! * Struct fields that can be loaned or "taken" -//! * Optional function arguments -//! * Nullable pointers -//! * Swapping things out of difficult situations -//! -//! Options are commonly paired with pattern matching to query the presence -//! of a value and take action, always accounting for the `None` case. -//! -//! ``` -//! # // FIXME This is not the greatest first example -//! // cow_says contains the word "moo" -//! let cow_says = Some("moo"); -//! // dog_says does not contain a value -//! let dog_says: Option<&str> = None; -//! -//! // Pattern match to retrieve the value -//! match (cow_says, dog_says) { -//! (Some(cow_words), Some(dog_words)) => { -//! println!("Cow says {} and dog says {}!", cow_words, dog_words); -//! } -//! (Some(cow_words), None) => println!("Cow says {}", cow_words), -//! (None, Some(dog_words)) => println!("Dog says {}", dog_words), -//! (None, None) => println!("Cow and dog are suspiciously silent") -//! } -//! ``` -//! -// -// FIXME: Show how `Option` is used in practice, with lots of methods -// -//! # Options and pointers ("nullable" pointers) -//! -//! Rust's pointer types must always point to a valid location; there are -//! no "null" pointers. Instead, Rust has *optional* pointers, like -//! the optional owned box, `Option>`. -//! -//! The following example uses `Option` to create an optional box of -//! `int`. Notice that in order to use the inner `int` value first the -//! `check_optional` function needs to use pattern matching to -//! determine whether the box has a value (i.e. it is `Some(...)`) or -//! not (`None`). -//! -//! ``` -//! let optional: Option> = None; -//! check_optional(&optional); -//! -//! let optional: Option> = Some(box 9000); -//! check_optional(&optional); -//! -//! fn check_optional(optional: &Option>) { -//! match *optional { -//! Some(ref p) => println!("have value {}", p), -//! None => println!("have no value") -//! } -//! } -//! ``` -//! -//! This usage of `Option` to create safe nullable pointers is so -//! common that Rust does special optimizations to make the -//! representation of `Option>` a single pointer. Optional pointers -//! in Rust are stored as efficiently as any other pointer type. -//! -//! # Examples -//! -//! Basic pattern matching on `Option`: -//! -//! ``` -//! let msg = Some("howdy"); -//! -//! // Take a reference to the contained string -//! match msg { -//! Some(ref m) => println!("{}", *m), -//! None => () -//! } -//! -//! // Remove the contained string, destroying the Option -//! let unwrapped_msg = match msg { -//! Some(m) => m, -//! None => "default message" -//! }; -//! ``` -//! -//! Initialize a result to `None` before a loop: -//! -//! ``` -//! enum Kingdom { Plant(uint, &'static str), Animal(uint, &'static str) } -//! -//! // A list of data to search through. -//! let all_the_big_things = [ -//! Plant(250, "redwood"), -//! Plant(230, "noble fir"), -//! Plant(229, "sugar pine"), -//! Animal(25, "blue whale"), -//! Animal(19, "fin whale"), -//! Animal(15, "north pacific right whale"), -//! ]; -//! -//! // We're going to search for the name of the biggest animal, -//! // but to start with we've just got `None`. -//! let mut name_of_biggest_animal = None; -//! let mut size_of_biggest_animal = 0; -//! for big_thing in all_the_big_things.iter() { -//! match *big_thing { -//! Animal(size, name) if size > size_of_biggest_animal => { -//! // Now we've found the name of some big animal -//! size_of_biggest_animal = size; -//! name_of_biggest_animal = Some(name); -//! } -//! Animal(..) | Plant(..) => () -//! } -//! } -//! -//! match name_of_biggest_animal { -//! Some(name) => println!("the biggest animal is {}", name), -//! None => println!("there are no animals :(") -//! } -//! ``` - -use any::Any; -use clone::Clone; -use cmp::{Eq, TotalEq, TotalOrd}; -use default::Default; -use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSize}; -use kinds::Send; -use mem; -use slice; - -/// The `Option` -#[deriving(Clone, Eq, Ord, TotalEq, TotalOrd, Show)] -pub enum Option { - /// No value - None, - /// Some value `T` - Some(T) -} - -///////////////////////////////////////////////////////////////////////////// -// Type implementation -///////////////////////////////////////////////////////////////////////////// - -impl Option { - ///////////////////////////////////////////////////////////////////////// - // Querying the contained values - ///////////////////////////////////////////////////////////////////////// - - /// Returns `true` if the option is a `Some` value - #[inline] - pub fn is_some(&self) -> bool { - match *self { - Some(_) => true, - None => false - } - } - - /// Returns `true` if the option is a `None` value - #[inline] - pub fn is_none(&self) -> bool { - !self.is_some() - } - - ///////////////////////////////////////////////////////////////////////// - // Adapter for working with references - ///////////////////////////////////////////////////////////////////////// - - /// Convert from `Option` to `Option<&T>` - /// - /// # Example - /// - /// Convert an `Option<~str>` into an `Option`, preserving the original. - /// The `map` method takes the `self` argument by value, consuming the original, - /// so this technique uses `as_ref` to first take an `Option` to a reference - /// to the value inside the original. - /// - /// ``` - /// let num_as_str: Option<~str> = Some("10".to_owned()); - /// // First, cast `Option<~str>` to `Option<&~str>` with `as_ref`, - /// // then consume *that* with `map`, leaving `num_as_str` on the stack. - /// let num_as_int: Option = num_as_str.as_ref().map(|n| n.len()); - /// println!("still can print num_as_str: {}", num_as_str); - /// ``` - #[inline] - pub fn as_ref<'r>(&'r self) -> Option<&'r T> { - match *self { Some(ref x) => Some(x), None => None } - } - - /// Convert from `Option` to `Option<&mut T>` - #[inline] - pub fn as_mut<'r>(&'r mut self) -> Option<&'r mut T> { - match *self { Some(ref mut x) => Some(x), None => None } - } - - /// Convert from `Option` to `&[T]` (without copying) - #[inline] - pub fn as_slice<'r>(&'r self) -> &'r [T] { - match *self { - Some(ref x) => slice::ref_slice(x), - None => &[] - } - } - - /// Convert from `Option` to `&mut [T]` (without copying) - #[inline] - pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [T] { - match *self { - Some(ref mut x) => slice::mut_ref_slice(x), - None => &mut [] - } - } - - ///////////////////////////////////////////////////////////////////////// - // Getting to contained values - ///////////////////////////////////////////////////////////////////////// - - /// Unwraps an option, yielding the content of a `Some` - /// - /// # Failure - /// - /// Fails if the value is a `None` with a custom failure message provided by `msg`. - #[inline] - pub fn expect(self, msg: M) -> T { - match self { - Some(val) => val, - None => fail!(msg), - } - } - - /// Moves a value out of an option type and returns it, consuming the `Option`. - /// - /// # Failure - /// - /// Fails if the self value equals `None`. - /// - /// # Safety note - /// - /// In general, because this function may fail, its use is discouraged. - /// Instead, prefer to use pattern matching and handle the `None` - /// case explicitly. - #[inline] - pub fn unwrap(self) -> T { - match self { - Some(val) => val, - None => fail!("called `Option::unwrap()` on a `None` value"), - } - } - - /// Returns the contained value or a default. - #[inline] - pub fn unwrap_or(self, def: T) -> T { - match self { - Some(x) => x, - None => def - } - } - - /// Returns the contained value or computes it from a closure. - #[inline] - pub fn unwrap_or_else(self, f: || -> T) -> T { - match self { - Some(x) => x, - None => f() - } - } - - ///////////////////////////////////////////////////////////////////////// - // Transforming contained values - ///////////////////////////////////////////////////////////////////////// - - /// Maps an `Option` to `Option` by applying a function to a contained value - /// - /// # Example - /// - /// Convert an `Option<~str>` into an `Option`, consuming the original: - /// - /// ``` - /// let num_as_str: Option<~str> = Some("10".to_owned()); - /// // `Option::map` takes self *by value*, consuming `num_as_str` - /// let num_as_int: Option = num_as_str.map(|n| n.len()); - /// ``` - #[inline] - pub fn map(self, f: |T| -> U) -> Option { - match self { Some(x) => Some(f(x)), None => None } - } - - /// Applies a function to the contained value or returns a default. - #[inline] - pub fn map_or(self, def: U, f: |T| -> U) -> U { - match self { None => def, Some(t) => f(t) } - } - - /// Applies a function to the contained value or does nothing. - /// Returns true if the contained value was mutated. - pub fn mutate(&mut self, f: |T| -> T) -> bool { - if self.is_some() { - *self = Some(f(self.take_unwrap())); - true - } else { false } - } - - /// Applies a function to the contained value or sets it to a default. - /// Returns true if the contained value was mutated, or false if set to the default. - pub fn mutate_or_set(&mut self, def: T, f: |T| -> T) -> bool { - if self.is_some() { - *self = Some(f(self.take_unwrap())); - true - } else { - *self = Some(def); - false - } - } - - ///////////////////////////////////////////////////////////////////////// - // Iterator constructors - ///////////////////////////////////////////////////////////////////////// - - /// Returns an iterator over the possibly contained value. - #[inline] - pub fn iter<'r>(&'r self) -> Item<&'r T> { - Item{opt: self.as_ref()} - } - - /// Returns a mutable iterator over the possibly contained value. - #[inline] - pub fn mut_iter<'r>(&'r mut self) -> Item<&'r mut T> { - Item{opt: self.as_mut()} - } - - /// Returns a consuming iterator over the possibly contained value. - #[inline] - pub fn move_iter(self) -> Item { - Item{opt: self} - } - - ///////////////////////////////////////////////////////////////////////// - // Boolean operations on the values, eager and lazy - ///////////////////////////////////////////////////////////////////////// - - /// Returns `None` if the option is `None`, otherwise returns `optb`. - #[inline] - pub fn and(self, optb: Option) -> Option { - match self { - Some(_) => optb, - None => None, - } - } - - /// Returns `None` if the option is `None`, otherwise calls `f` with the - /// wrapped value and returns the result. - #[inline] - pub fn and_then(self, f: |T| -> Option) -> Option { - match self { - Some(x) => f(x), - None => None, - } - } - - /// Returns the option if it contains a value, otherwise returns `optb`. - #[inline] - pub fn or(self, optb: Option) -> Option { - match self { - Some(_) => self, - None => optb - } - } - - /// Returns the option if it contains a value, otherwise calls `f` and - /// returns the result. - #[inline] - pub fn or_else(self, f: || -> Option) -> Option { - match self { - Some(_) => self, - None => f() - } - } - - ///////////////////////////////////////////////////////////////////////// - // Misc - ///////////////////////////////////////////////////////////////////////// - - /// Takes the value out of the option, leaving a `None` in its place. - #[inline] - pub fn take(&mut self) -> Option { - mem::replace(self, None) - } - - /// Filters an optional value using a given function. - #[inline(always)] - pub fn filtered(self, f: |t: &T| -> bool) -> Option { - match self { - Some(x) => if f(&x) { Some(x) } else { None }, - None => None - } - } - - /// Applies a function zero or more times until the result is `None`. - #[inline] - pub fn while_some(self, f: |v: T| -> Option) { - let mut opt = self; - loop { - match opt { - Some(x) => opt = f(x), - None => break - } - } - } - - ///////////////////////////////////////////////////////////////////////// - // Common special cases - ///////////////////////////////////////////////////////////////////////// - - /// The option dance. Moves a value out of an option type and returns it, - /// replacing the original with `None`. - /// - /// # Failure - /// - /// Fails if the value equals `None`. - #[inline] - pub fn take_unwrap(&mut self) -> T { - match self.take() { - Some(x) => x, - None => fail!("called `Option::take_unwrap()` on a `None` value") - } - } - - /// Gets an immutable reference to the value inside an option. - /// - /// # Failure - /// - /// Fails if the value equals `None` - /// - /// # Safety note - /// - /// In general, because this function may fail, its use is discouraged - /// (calling `get` on `None` is akin to dereferencing a null pointer). - /// Instead, prefer to use pattern matching and handle the `None` - /// case explicitly. - #[inline] - pub fn get_ref<'a>(&'a self) -> &'a T { - match *self { - Some(ref x) => x, - None => fail!("called `Option::get_ref()` on a `None` value"), - } - } - - /// Gets a mutable reference to the value inside an option. - /// - /// # Failure - /// - /// Fails if the value equals `None` - /// - /// # Safety note - /// - /// In general, because this function may fail, its use is discouraged - /// (calling `get` on `None` is akin to dereferencing a null pointer). - /// Instead, prefer to use pattern matching and handle the `None` - /// case explicitly. - #[inline] - pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T { - match *self { - Some(ref mut x) => x, - None => fail!("called `Option::get_mut_ref()` on a `None` value"), - } - } -} - -impl Option { - /// Returns the contained value or a default - /// - /// Consumes the `self` argument then, if `Some`, returns the contained - /// value, otherwise if `None`, returns the default value for that - /// type. - /// - /// # Example - /// - /// Convert a string to an integer, turning poorly-formed strings - /// into 0 (the default value for integers). `from_str` converts - /// a string to any other type that implements `FromStr`, returning - /// `None` on error. - /// - /// ``` - /// let good_year_from_input = "1909"; - /// let bad_year_from_input = "190blarg"; - /// let good_year = from_str(good_year_from_input).unwrap_or_default(); - /// let bad_year = from_str(bad_year_from_input).unwrap_or_default(); - /// - /// assert_eq!(1909, good_year); - /// assert_eq!(0, bad_year); - /// ``` - #[inline] - pub fn unwrap_or_default(self) -> T { - match self { - Some(x) => x, - None => Default::default() - } - } -} - -///////////////////////////////////////////////////////////////////////////// -// Trait implementations -///////////////////////////////////////////////////////////////////////////// - -impl Default for Option { - #[inline] - fn default() -> Option { None } -} - -///////////////////////////////////////////////////////////////////////////// -// The Option Iterator -///////////////////////////////////////////////////////////////////////////// - -/// An `Option` iterator that yields either one or zero elements -/// -/// The `Item` iterator is returned by the `iter`, `mut_iter` and `move_iter` -/// methods on `Option`. -#[deriving(Clone)] -pub struct Item { - opt: Option -} - -impl Iterator for Item { - #[inline] - fn next(&mut self) -> Option { - self.opt.take() - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - match self.opt { - Some(_) => (1, Some(1)), - None => (0, Some(0)), - } - } -} - -impl DoubleEndedIterator for Item { - #[inline] - fn next_back(&mut self) -> Option { - self.opt.take() - } -} - -impl ExactSize for Item {} - -///////////////////////////////////////////////////////////////////////////// -// Free functions -///////////////////////////////////////////////////////////////////////////// - -/// Takes each element in the `Iterator`: if it is `None`, no further -/// elements are taken, and the `None` is returned. Should no `None` occur, a -/// vector containing the values of each `Option` is returned. -/// -/// Here is an example which increments every integer in a vector, -/// checking for overflow: -/// -/// fn inc_conditionally(x: uint) -> Option { -/// if x == uint::MAX { return None; } -/// else { return Some(x+1u); } -/// } -/// let v = [1u, 2, 3]; -/// let res = collect(v.iter().map(|&x| inc_conditionally(x))); -/// assert!(res == Some(~[2u, 3, 4])); -#[inline] -pub fn collect>, V: FromIterator>(iter: Iter) -> Option { - // FIXME(#11084): This should be twice as fast once this bug is closed. - let mut iter = iter.scan(false, |state, x| { - match x { - Some(x) => Some(x), - None => { - *state = true; - None - } - } - }); - - let v: V = FromIterator::from_iter(iter.by_ref()); - - if iter.state { - None - } else { - Some(v) - } -} - -///////////////////////////////////////////////////////////////////////////// -// Tests -///////////////////////////////////////////////////////////////////////////// - -#[cfg(test)] -mod tests { - use super::*; - use prelude::*; - - use iter::range; - use str::StrSlice; - use kinds::marker; - use slice::ImmutableVector; - - #[test] - fn test_get_ptr() { - unsafe { - let x = box 0; - let addr_x: *int = ::cast::transmute(&*x); - let opt = Some(x); - let y = opt.unwrap(); - let addr_y: *int = ::cast::transmute(&*y); - assert_eq!(addr_x, addr_y); - } - } - - #[test] - fn test_get_str() { - let x = "test".to_owned(); - let addr_x = x.as_ptr(); - let opt = Some(x); - let y = opt.unwrap(); - let addr_y = y.as_ptr(); - assert_eq!(addr_x, addr_y); - } - - #[test] - fn test_get_resource() { - use rc::Rc; - use cell::RefCell; - - struct R { - i: Rc>, - } - - #[unsafe_destructor] - impl ::ops::Drop for R { - fn drop(&mut self) { - let ii = &*self.i; - let i = ii.borrow().clone(); - *ii.borrow_mut() = i + 1; - } - } - - fn R(i: Rc>) -> R { - R { - i: i - } - } - - let i = Rc::new(RefCell::new(0)); - { - let x = R(i.clone()); - let opt = Some(x); - let _y = opt.unwrap(); - } - assert_eq!(*i.borrow(), 1); - } - - #[test] - fn test_option_dance() { - let x = Some(()); - let mut y = Some(5); - let mut y2 = 0; - for _x in x.iter() { - y2 = y.take_unwrap(); - } - assert_eq!(y2, 5); - assert!(y.is_none()); - } - - #[test] #[should_fail] - fn test_option_too_much_dance() { - let mut y = Some(marker::NoCopy); - let _y2 = y.take_unwrap(); - let _y3 = y.take_unwrap(); - } - - #[test] - fn test_and() { - let x: Option = Some(1); - assert_eq!(x.and(Some(2)), Some(2)); - assert_eq!(x.and(None::), None); - - let x: Option = None; - assert_eq!(x.and(Some(2)), None); - assert_eq!(x.and(None::), None); - } - - #[test] - fn test_and_then() { - let x: Option = Some(1); - assert_eq!(x.and_then(|x| Some(x + 1)), Some(2)); - assert_eq!(x.and_then(|_| None::), None); - - let x: Option = None; - assert_eq!(x.and_then(|x| Some(x + 1)), None); - assert_eq!(x.and_then(|_| None::), None); - } - - #[test] - fn test_or() { - let x: Option = Some(1); - assert_eq!(x.or(Some(2)), Some(1)); - assert_eq!(x.or(None), Some(1)); - - let x: Option = None; - assert_eq!(x.or(Some(2)), Some(2)); - assert_eq!(x.or(None), None); - } - - #[test] - fn test_or_else() { - let x: Option = Some(1); - assert_eq!(x.or_else(|| Some(2)), Some(1)); - assert_eq!(x.or_else(|| None), Some(1)); - - let x: Option = None; - assert_eq!(x.or_else(|| Some(2)), Some(2)); - assert_eq!(x.or_else(|| None), None); - } - - #[test] - fn test_option_while_some() { - let mut i = 0; - Some(10).while_some(|j| { - i += 1; - if j > 0 { - Some(j-1) - } else { - None - } - }); - assert_eq!(i, 11); - } - - #[test] - fn test_unwrap() { - assert_eq!(Some(1).unwrap(), 1); - assert_eq!(Some("hello".to_owned()).unwrap(), "hello".to_owned()); - } - - #[test] - #[should_fail] - fn test_unwrap_fail1() { - let x: Option = None; - x.unwrap(); - } - - #[test] - #[should_fail] - fn test_unwrap_fail2() { - let x: Option<~str> = None; - x.unwrap(); - } - - #[test] - fn test_unwrap_or() { - let x: Option = Some(1); - assert_eq!(x.unwrap_or(2), 1); - - let x: Option = None; - assert_eq!(x.unwrap_or(2), 2); - } - - #[test] - fn test_unwrap_or_else() { - let x: Option = Some(1); - assert_eq!(x.unwrap_or_else(|| 2), 1); - - let x: Option = None; - assert_eq!(x.unwrap_or_else(|| 2), 2); - } - - #[test] - fn test_filtered() { - let some_stuff = Some(42); - let modified_stuff = some_stuff.filtered(|&x| {x < 10}); - assert_eq!(some_stuff.unwrap(), 42); - assert!(modified_stuff.is_none()); - } - - #[test] - fn test_iter() { - let val = 5; - - let x = Some(val); - let mut it = x.iter(); - - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next(), Some(&val)); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - - #[test] - fn test_mut_iter() { - let val = 5; - let new_val = 11; - - let mut x = Some(val); - { - let mut it = x.mut_iter(); - - assert_eq!(it.size_hint(), (1, Some(1))); - - match it.next() { - Some(interior) => { - assert_eq!(*interior, val); - *interior = new_val; - } - None => assert!(false), - } - - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - assert_eq!(x, Some(new_val)); - } - - #[test] - fn test_ord() { - let small = Some(1.0); - let big = Some(5.0); - let nan = Some(0.0/0.0); - assert!(!(nan < big)); - assert!(!(nan > big)); - assert!(small < big); - assert!(None < big); - assert!(big > None); - } - - #[test] - fn test_mutate() { - let mut x = Some(3i); - assert!(x.mutate(|i| i+1)); - assert_eq!(x, Some(4i)); - assert!(x.mutate_or_set(0, |i| i+1)); - assert_eq!(x, Some(5i)); - x = None; - assert!(!x.mutate(|i| i+1)); - assert_eq!(x, None); - assert!(!x.mutate_or_set(0i, |i| i+1)); - assert_eq!(x, Some(0i)); - } - - #[test] - fn test_collect() { - let v: Option<~[int]> = collect(range(0, 0) - .map(|_| Some(0))); - assert_eq!(v, Some(box [])); - - let v: Option<~[int]> = collect(range(0, 3) - .map(|x| Some(x))); - assert_eq!(v, Some(box [0, 1, 2])); - - let v: Option<~[int]> = collect(range(0, 3) - .map(|x| if x > 1 { None } else { Some(x) })); - assert_eq!(v, None); - - // test that it does not take more elements than it needs - let mut functions = [|| Some(()), || None, || fail!()]; - - let v: Option<~[()]> = collect(functions.mut_iter().map(|f| (*f)())); - - assert_eq!(v, None); - } -} -- cgit 1.4.1-3-g733a5 From b024ba544c8cf831423cdd24d2dc516d66dc6269 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 21:41:03 -0700 Subject: core: Inherit the iter module --- src/libcore/iter.rs | 3090 +++++++++++++++++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 1 + src/libstd/fmt/mod.rs | 14 + src/libstd/iter.rs | 3090 ------------------------------------------------- src/libstd/lib.rs | 2 +- 5 files changed, 3106 insertions(+), 3091 deletions(-) create mode 100644 src/libcore/iter.rs delete mode 100644 src/libstd/iter.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs new file mode 100644 index 00000000000..6d40db1be4d --- /dev/null +++ b/src/libcore/iter.rs @@ -0,0 +1,3090 @@ +// 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. + +/*! + +Composable external iterators + +# The `Iterator` trait + +This module defines Rust's core iteration trait. The `Iterator` trait has one +unimplemented method, `next`. All other methods are derived through default +methods to perform operations such as `zip`, `chain`, `enumerate`, and `fold`. + +The goal of this module is to unify iteration across all containers in Rust. +An iterator can be considered as a state machine which is used to track which +element will be yielded next. + +There are various extensions also defined in this module to assist with various +types of iteration, such as the `DoubleEndedIterator` for iterating in reverse, +the `FromIterator` trait for creating a container from an iterator, and much +more. + +## Rust's `for` loop + +The special syntax used by rust's `for` loop is based around the `Iterator` +trait defined in this module. For loops can be viewed as a syntactical expansion +into a `loop`, for example, the `for` loop in this example is essentially +translated to the `loop` below. + +```rust +let values = ~[1, 2, 3]; + +// "Syntactical sugar" taking advantage of an iterator +for &x in values.iter() { + println!("{}", x); +} + +// Rough translation of the iteration without a `for` iterator. +let mut it = values.iter(); +loop { + match it.next() { + Some(&x) => { + println!("{}", x); + } + None => { break } + } +} +``` + +This `for` loop syntax can be applied to any iterator over any type. + +## Iteration protocol and more + +More detailed information about iterators can be found in the [container +guide](http://static.rust-lang.org/doc/master/guide-container.html) with +the rest of the rust manuals. + +*/ + +use cmp; +use num::{Zero, One, CheckedAdd, CheckedSub, Saturating, ToPrimitive, Int}; +use option::{Option, Some, None}; +use ops::{Add, Mul, Sub}; +use cmp::{Eq, Ord, TotalOrd}; +use clone::Clone; +use uint; +use mem; + +/// Conversion from an `Iterator` +pub trait FromIterator { + /// Build a container with elements from an external iterator. + fn from_iter>(iterator: T) -> Self; +} + +/// A type growable from an `Iterator` implementation +pub trait Extendable: FromIterator { + /// Extend a container with the elements yielded by an iterator + fn extend>(&mut self, iterator: T); +} + +/// An interface for dealing with "external iterators". These types of iterators +/// can be resumed at any time as all state is stored internally as opposed to +/// being located on the call stack. +/// +/// The Iterator protocol states that an iterator yields a (potentially-empty, +/// potentially-infinite) sequence of values, and returns `None` to signal that +/// it's finished. The Iterator protocol does not define behavior after `None` +/// is returned. A concrete Iterator implementation may choose to behave however +/// it wishes, either by returning `None` infinitely, or by doing something +/// else. +pub trait Iterator { + /// Advance the iterator and return the next value. Return `None` when the end is reached. + fn next(&mut self) -> Option; + + /// Return a lower bound and upper bound on the remaining length of the iterator. + /// + /// The common use case for the estimate is pre-allocating space to store the results. + #[inline] + fn size_hint(&self) -> (uint, Option) { (0, None) } + + /// Chain this iterator with another, returning a new iterator which will + /// finish iterating over the current iterator, and then it will iterate + /// over the other specified iterator. + /// + /// # Example + /// + /// ```rust + /// let a = [0]; + /// let b = [1]; + /// let mut it = a.iter().chain(b.iter()); + /// assert_eq!(it.next().unwrap(), &0); + /// assert_eq!(it.next().unwrap(), &1); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn chain>(self, other: U) -> Chain { + Chain{a: self, b: other, flag: false} + } + + /// Creates an iterator which iterates over both this and the specified + /// iterators simultaneously, yielding the two elements as pairs. When + /// either iterator returns None, all further invocations of next() will + /// return None. + /// + /// # Example + /// + /// ```rust + /// let a = [0]; + /// let b = [1]; + /// let mut it = a.iter().zip(b.iter()); + /// assert_eq!(it.next().unwrap(), (&0, &1)); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn zip>(self, other: U) -> Zip { + Zip{a: self, b: other} + } + + /// Creates a new iterator which will apply the specified function to each + /// element returned by the first, yielding the mapped element instead. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2]; + /// let mut it = a.iter().map(|&x| 2 * x); + /// assert_eq!(it.next().unwrap(), 2); + /// assert_eq!(it.next().unwrap(), 4); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn map<'r, B>(self, f: |A|: 'r -> B) -> Map<'r, A, B, Self> { + Map{iter: self, f: f} + } + + /// Creates an iterator which applies the predicate to each element returned + /// by this iterator. Only elements which have the predicate evaluate to + /// `true` will be yielded. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2]; + /// let mut it = a.iter().filter(|&x| *x > 1); + /// assert_eq!(it.next().unwrap(), &2); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn filter<'r>(self, predicate: |&A|: 'r -> bool) -> Filter<'r, A, Self> { + Filter{iter: self, predicate: predicate} + } + + /// Creates an iterator which both filters and maps elements. + /// If the specified function returns None, the element is skipped. + /// Otherwise the option is unwrapped and the new value is yielded. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2]; + /// let mut it = a.iter().filter_map(|&x| if x > 1 {Some(2 * x)} else {None}); + /// assert_eq!(it.next().unwrap(), 4); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn filter_map<'r, B>(self, f: |A|: 'r -> Option) -> FilterMap<'r, A, B, Self> { + FilterMap { iter: self, f: f } + } + + /// Creates an iterator which yields a pair of the value returned by this + /// iterator plus the current index of iteration. + /// + /// # Example + /// + /// ```rust + /// let a = [100, 200]; + /// let mut it = a.iter().enumerate(); + /// assert_eq!(it.next().unwrap(), (0, &100)); + /// assert_eq!(it.next().unwrap(), (1, &200)); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn enumerate(self) -> Enumerate { + Enumerate{iter: self, count: 0} + } + + + /// Creates an iterator that has a `.peek()` method + /// that returns an optional reference to the next element. + /// + /// # Example + /// + /// ```rust + /// let xs = [100, 200, 300]; + /// let mut it = xs.iter().map(|x| *x).peekable(); + /// assert_eq!(it.peek().unwrap(), &100); + /// assert_eq!(it.next().unwrap(), 100); + /// assert_eq!(it.next().unwrap(), 200); + /// assert_eq!(it.peek().unwrap(), &300); + /// assert_eq!(it.peek().unwrap(), &300); + /// assert_eq!(it.next().unwrap(), 300); + /// assert!(it.peek().is_none()); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn peekable(self) -> Peekable { + Peekable{iter: self, peeked: None} + } + + /// Creates an iterator which invokes the predicate on elements until it + /// returns false. Once the predicate returns false, all further elements are + /// yielded. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 2, 1]; + /// let mut it = a.iter().skip_while(|&a| *a < 3); + /// assert_eq!(it.next().unwrap(), &3); + /// assert_eq!(it.next().unwrap(), &2); + /// assert_eq!(it.next().unwrap(), &1); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn skip_while<'r>(self, predicate: |&A|: 'r -> bool) -> SkipWhile<'r, A, Self> { + SkipWhile{iter: self, flag: false, predicate: predicate} + } + + /// Creates an iterator which yields elements so long as the predicate + /// returns true. After the predicate returns false for the first time, no + /// further elements will be yielded. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 2, 1]; + /// let mut it = a.iter().take_while(|&a| *a < 3); + /// assert_eq!(it.next().unwrap(), &1); + /// assert_eq!(it.next().unwrap(), &2); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn take_while<'r>(self, predicate: |&A|: 'r -> bool) -> TakeWhile<'r, A, Self> { + TakeWhile{iter: self, flag: false, predicate: predicate} + } + + /// Creates an iterator which skips the first `n` elements of this iterator, + /// and then it yields all further items. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter().skip(3); + /// assert_eq!(it.next().unwrap(), &4); + /// assert_eq!(it.next().unwrap(), &5); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn skip(self, n: uint) -> Skip { + Skip{iter: self, n: n} + } + + /// Creates an iterator which yields the first `n` elements of this + /// iterator, and then it will always return None. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter().take(3); + /// assert_eq!(it.next().unwrap(), &1); + /// assert_eq!(it.next().unwrap(), &2); + /// assert_eq!(it.next().unwrap(), &3); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn take(self, n: uint) -> Take { + Take{iter: self, n: n} + } + + /// Creates a new iterator which behaves in a similar fashion to fold. + /// There is a state which is passed between each iteration and can be + /// mutated as necessary. The yielded values from the closure are yielded + /// from the Scan instance when not None. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter().scan(1, |fac, &x| { + /// *fac = *fac * x; + /// Some(*fac) + /// }); + /// assert_eq!(it.next().unwrap(), 1); + /// assert_eq!(it.next().unwrap(), 2); + /// assert_eq!(it.next().unwrap(), 6); + /// assert_eq!(it.next().unwrap(), 24); + /// assert_eq!(it.next().unwrap(), 120); + /// assert!(it.next().is_none()); + /// ``` + #[inline] + fn scan<'r, St, B>(self, initial_state: St, f: |&mut St, A|: 'r -> Option) + -> Scan<'r, A, B, Self, St> { + Scan{iter: self, f: f, state: initial_state} + } + + /// Creates an iterator that maps each element to an iterator, + /// and yields the elements of the produced iterators + /// + /// # Example + /// + /// ```rust + /// use std::iter::count; + /// + /// let xs = [2u, 3]; + /// let ys = [0u, 1, 0, 1, 2]; + /// let mut it = xs.iter().flat_map(|&x| count(0u, 1).take(x)); + /// // Check that `it` has the same elements as `ys` + /// let mut i = 0; + /// for x in it { + /// assert_eq!(x, ys[i]); + /// i += 1; + /// } + /// ``` + #[inline] + fn flat_map<'r, B, U: Iterator>(self, f: |A|: 'r -> U) + -> FlatMap<'r, A, Self, U> { + FlatMap{iter: self, f: f, frontiter: None, backiter: None } + } + + /// Creates an iterator that yields `None` forever after the underlying + /// iterator yields `None`. Random-access iterator behavior is not + /// affected, only single and double-ended iterator behavior. + /// + /// # Example + /// + /// ```rust + /// fn process>(it: U) -> int { + /// let mut it = it.fuse(); + /// let mut sum = 0; + /// for x in it { + /// if x > 5 { + /// continue; + /// } + /// sum += x; + /// } + /// // did we exhaust the iterator? + /// if it.next().is_none() { + /// sum += 1000; + /// } + /// sum + /// } + /// let x = ~[1,2,3,7,8,9]; + /// assert_eq!(process(x.move_iter()), 1006); + /// ``` + #[inline] + fn fuse(self) -> Fuse { + Fuse{iter: self, done: false} + } + + /// Creates an iterator that calls a function with a reference to each + /// element before yielding it. This is often useful for debugging an + /// iterator pipeline. + /// + /// # Example + /// + /// ```rust + /// use std::iter::AdditiveIterator; + /// + /// let xs = [1u, 4, 2, 3, 8, 9, 6]; + /// let sum = xs.iter() + /// .map(|&x| x) + /// .inspect(|&x| println!("filtering {}", x)) + /// .filter(|&x| x % 2 == 0) + /// .inspect(|&x| println!("{} made it through", x)) + /// .sum(); + /// println!("{}", sum); + /// ``` + #[inline] + fn inspect<'r>(self, f: |&A|: 'r) -> Inspect<'r, A, Self> { + Inspect{iter: self, f: f} + } + + /// Creates a wrapper around a mutable reference to the iterator. + /// + /// This is useful to allow applying iterator adaptors while still + /// retaining ownership of the original iterator value. + /// + /// # Example + /// + /// ```rust + /// let mut xs = range(0, 10); + /// // sum the first five values + /// let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b); + /// assert!(partial_sum == 10); + /// // xs.next() is now `5` + /// assert!(xs.next() == Some(5)); + /// ``` + fn by_ref<'r>(&'r mut self) -> ByRef<'r, Self> { + ByRef{iter: self} + } + + /// Apply a function to each element, or stop iterating if the + /// function returns `false`. + /// + /// # Example + /// + /// ```rust + /// range(0, 5).advance(|x| {print!("{} ", x); true}); + /// ``` + #[inline] + fn advance(&mut self, f: |A| -> bool) -> bool { + loop { + match self.next() { + Some(x) => { + if !f(x) { return false; } + } + None => { return true; } + } + } + } + + /// Loops through the entire iterator, collecting all of the elements into + /// a container implementing `FromIterator`. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// let b: ~[int] = a.iter().map(|&x| x).collect(); + /// assert!(a == b); + /// ``` + #[inline] + fn collect>(&mut self) -> B { + FromIterator::from_iter(self.by_ref()) + } + + /// Loops through `n` iterations, returning the `n`th element of the + /// iterator. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter(); + /// assert!(it.nth(2).unwrap() == &3); + /// assert!(it.nth(2) == None); + /// ``` + #[inline] + fn nth(&mut self, mut n: uint) -> Option { + loop { + match self.next() { + Some(x) => if n == 0 { return Some(x) }, + None => return None + } + n -= 1; + } + } + + /// Loops through the entire iterator, returning the last element of the + /// iterator. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// assert!(a.iter().last().unwrap() == &5); + /// ``` + #[inline] + fn last(&mut self) -> Option { + let mut last = None; + for x in *self { last = Some(x); } + last + } + + /// Performs a fold operation over the entire iterator, returning the + /// eventual state at the end of the iteration. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// assert!(a.iter().fold(0, |a, &b| a + b) == 15); + /// ``` + #[inline] + fn fold(&mut self, init: B, f: |B, A| -> B) -> B { + let mut accum = init; + loop { + match self.next() { + Some(x) => { accum = f(accum, x); } + None => { break; } + } + } + accum + } + + /// Counts the number of elements in this iterator. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter(); + /// assert!(it.len() == 5); + /// assert!(it.len() == 0); + /// ``` + #[inline] + fn len(&mut self) -> uint { + self.fold(0, |cnt, _x| cnt + 1) + } + + /// Tests whether the predicate holds true for all elements in the iterator. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// assert!(a.iter().all(|x| *x > 0)); + /// assert!(!a.iter().all(|x| *x > 2)); + /// ``` + #[inline] + fn all(&mut self, f: |A| -> bool) -> bool { + for x in *self { if !f(x) { return false; } } + true + } + + /// Tests whether any element of an iterator satisfies the specified + /// predicate. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter(); + /// assert!(it.any(|x| *x == 3)); + /// assert!(!it.any(|x| *x == 3)); + /// ``` + #[inline] + fn any(&mut self, f: |A| -> bool) -> bool { + for x in *self { if f(x) { return true; } } + false + } + + /// Return the first element satisfying the specified predicate + #[inline] + fn find(&mut self, predicate: |&A| -> bool) -> Option { + for x in *self { + if predicate(&x) { return Some(x) } + } + None + } + + /// Return the index of the first element satisfying the specified predicate + #[inline] + fn position(&mut self, predicate: |A| -> bool) -> Option { + let mut i = 0; + for x in *self { + if predicate(x) { + return Some(i); + } + i += 1; + } + None + } + + /// Count the number of elements satisfying the specified predicate + #[inline] + fn count(&mut self, predicate: |A| -> bool) -> uint { + let mut i = 0; + for x in *self { + if predicate(x) { i += 1 } + } + i + } + + /// Return the element that gives the maximum value from the + /// specified function. + /// + /// # Example + /// + /// ```rust + /// let xs = [-3i, 0, 1, 5, -10]; + /// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10); + /// ``` + #[inline] + fn max_by(&mut self, f: |&A| -> B) -> Option { + self.fold(None, |max: Option<(A, B)>, x| { + let x_val = f(&x); + match max { + None => Some((x, x_val)), + Some((y, y_val)) => if x_val > y_val { + Some((x, x_val)) + } else { + Some((y, y_val)) + } + } + }).map(|(x, _)| x) + } + + /// Return the element that gives the minimum value from the + /// specified function. + /// + /// # Example + /// + /// ```rust + /// let xs = [-3i, 0, 1, 5, -10]; + /// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0); + /// ``` + #[inline] + fn min_by(&mut self, f: |&A| -> B) -> Option { + self.fold(None, |min: Option<(A, B)>, x| { + let x_val = f(&x); + match min { + None => Some((x, x_val)), + Some((y, y_val)) => if x_val < y_val { + Some((x, x_val)) + } else { + Some((y, y_val)) + } + } + }).map(|(x, _)| x) + } +} + +/// A range iterator able to yield elements from both ends +pub trait DoubleEndedIterator: Iterator { + /// Yield an element from the end of the range, returning `None` if the range is empty. + fn next_back(&mut self) -> Option; + + /// Change the direction of the iterator + /// + /// The flipped iterator swaps the ends on an iterator that can already + /// be iterated from the front and from the back. + /// + /// + /// If the iterator also implements RandomAccessIterator, the flipped + /// iterator is also random access, with the indices starting at the back + /// of the original iterator. + /// + /// Note: Random access with flipped indices still only applies to the first + /// `uint::MAX` elements of the original iterator. + #[inline] + fn rev(self) -> Rev { + Rev{iter: self} + } +} + +/// A double-ended iterator yielding mutable references +pub trait MutableDoubleEndedIterator { + // FIXME: #5898: should be called `reverse` + /// Use an iterator to reverse a container in-place + fn reverse_(&mut self); +} + +impl<'a, A, T: DoubleEndedIterator<&'a mut A>> MutableDoubleEndedIterator for T { + // FIXME: #5898: should be called `reverse` + /// Use an iterator to reverse a container in-place + fn reverse_(&mut self) { + loop { + match (self.next(), self.next_back()) { + (Some(x), Some(y)) => mem::swap(x, y), + _ => break + } + } + } +} + + +/// An object implementing random access indexing by `uint` +/// +/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`. +pub trait RandomAccessIterator: Iterator { + /// Return the number of indexable elements. At most `std::uint::MAX` + /// elements are indexable, even if the iterator represents a longer range. + fn indexable(&self) -> uint; + + /// Return an element at an index + fn idx(&mut self, index: uint) -> Option; +} + +/// An iterator that knows its exact length +/// +/// This trait is a helper for iterators like the vector iterator, so that +/// it can support double-ended enumeration. +/// +/// `Iterator::size_hint` *must* return the exact size of the iterator. +/// Note that the size must fit in `uint`. +pub trait ExactSize : DoubleEndedIterator { + /// Return the index of the last element satisfying the specified predicate + /// + /// If no element matches, None is returned. + #[inline] + fn rposition(&mut self, predicate: |A| -> bool) -> Option { + let (lower, upper) = self.size_hint(); + assert!(upper == Some(lower)); + let mut i = lower; + loop { + match self.next_back() { + None => break, + Some(x) => { + i = match i.checked_sub(&1) { + Some(x) => x, + None => fail!("rposition: incorrect ExactSize") + }; + if predicate(x) { + return Some(i) + } + } + } + } + None + } +} + +// All adaptors that preserve the size of the wrapped iterator are fine +// Adaptors that may overflow in `size_hint` are not, i.e. `Chain`. +impl> ExactSize<(uint, A)> for Enumerate {} +impl<'a, A, T: ExactSize> ExactSize for Inspect<'a, A, T> {} +impl> ExactSize for Rev {} +impl<'a, A, B, T: ExactSize> ExactSize for Map<'a, A, B, T> {} +impl, U: ExactSize> ExactSize<(A, B)> for Zip {} + +/// An double-ended iterator with the direction inverted +#[deriving(Clone)] +pub struct Rev { + iter: T +} + +impl> Iterator for Rev { + #[inline] + fn next(&mut self) -> Option { self.iter.next_back() } + #[inline] + fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } +} + +impl> DoubleEndedIterator for Rev { + #[inline] + fn next_back(&mut self) -> Option { self.iter.next() } +} + +impl + RandomAccessIterator> RandomAccessIterator + for Rev { + #[inline] + fn indexable(&self) -> uint { self.iter.indexable() } + #[inline] + fn idx(&mut self, index: uint) -> Option { + let amt = self.indexable(); + self.iter.idx(amt - index - 1) + } +} + +/// A mutable reference to an iterator +pub struct ByRef<'a, T> { + iter: &'a mut T +} + +impl<'a, A, T: Iterator> Iterator for ByRef<'a, T> { + #[inline] + fn next(&mut self) -> Option { self.iter.next() } + #[inline] + fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } +} + +impl<'a, A, T: DoubleEndedIterator> DoubleEndedIterator for ByRef<'a, T> { + #[inline] + fn next_back(&mut self) -> Option { self.iter.next_back() } +} + +/// A trait for iterators over elements which can be added together +pub trait AdditiveIterator { + /// Iterates over the entire iterator, summing up all the elements + /// + /// # Example + /// + /// ```rust + /// use std::iter::AdditiveIterator; + /// + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter().map(|&x| x); + /// assert!(it.sum() == 15); + /// ``` + fn sum(&mut self) -> A; +} + +impl + Zero, T: Iterator> AdditiveIterator for T { + #[inline] + fn sum(&mut self) -> A { + let zero: A = Zero::zero(); + self.fold(zero, |s, x| s + x) + } +} + +/// A trait for iterators over elements whose elements can be multiplied +/// together. +pub trait MultiplicativeIterator { + /// Iterates over the entire iterator, multiplying all the elements + /// + /// # Example + /// + /// ```rust + /// use std::iter::{count, MultiplicativeIterator}; + /// + /// fn factorial(n: uint) -> uint { + /// count(1u, 1).take_while(|&i| i <= n).product() + /// } + /// assert!(factorial(0) == 1); + /// assert!(factorial(1) == 1); + /// assert!(factorial(5) == 120); + /// ``` + fn product(&mut self) -> A; +} + +impl + One, T: Iterator> MultiplicativeIterator for T { + #[inline] + fn product(&mut self) -> A { + let one: A = One::one(); + self.fold(one, |p, x| p * x) + } +} + +/// A trait for iterators over elements which can be compared to one another. +/// The type of each element must ascribe to the `Ord` trait. +pub trait OrdIterator { + /// Consumes the entire iterator to return the maximum element. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// assert!(a.iter().max().unwrap() == &5); + /// ``` + fn max(&mut self) -> Option; + + /// Consumes the entire iterator to return the minimum element. + /// + /// # Example + /// + /// ```rust + /// let a = [1, 2, 3, 4, 5]; + /// assert!(a.iter().min().unwrap() == &1); + /// ``` + fn min(&mut self) -> Option; + + /// `min_max` finds the minimum and maximum elements in the iterator. + /// + /// The return type `MinMaxResult` is an enum of three variants: + /// - `NoElements` if the iterator is empty. + /// - `OneElement(x)` if the iterator has exactly one element. + /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two values are equal if and only if + /// there is more than one element in the iterator and all elements are equal. + /// + /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons, + /// and so faster than calling `min` and `max separately which does `2 * n` comparisons. + /// + /// # Example + /// + /// ```rust + /// use std::iter::{NoElements, OneElement, MinMax}; + /// + /// let v: [int, ..0] = []; + /// assert_eq!(v.iter().min_max(), NoElements); + /// + /// let v = [1i]; + /// assert!(v.iter().min_max() == OneElement(&1)); + /// + /// let v = [1i, 2, 3, 4, 5]; + /// assert!(v.iter().min_max() == MinMax(&1, &5)); + /// + /// let v = [1i, 2, 3, 4, 5, 6]; + /// assert!(v.iter().min_max() == MinMax(&1, &6)); + /// + /// let v = [1i, 1, 1, 1]; + /// assert!(v.iter().min_max() == MinMax(&1, &1)); + /// ``` + fn min_max(&mut self) -> MinMaxResult; +} + +impl> OrdIterator for T { + #[inline] + fn max(&mut self) -> Option { + self.fold(None, |max, x| { + match max { + None => Some(x), + Some(y) => Some(cmp::max(x, y)) + } + }) + } + + #[inline] + fn min(&mut self) -> Option { + self.fold(None, |min, x| { + match min { + None => Some(x), + Some(y) => Some(cmp::min(x, y)) + } + }) + } + + fn min_max(&mut self) -> MinMaxResult { + let (mut min, mut max) = match self.next() { + None => return NoElements, + Some(x) => { + match self.next() { + None => return OneElement(x), + Some(y) => if x < y {(x, y)} else {(y,x)} + } + } + }; + + loop { + // `first` and `second` are the two next elements we want to look at. + // We first compare `first` and `second` (#1). The smaller one is then compared to + // current minimum (#2). The larger one is compared to current maximum (#3). This + // way we do 3 comparisons for 2 elements. + let first = match self.next() { + None => break, + Some(x) => x + }; + let second = match self.next() { + None => { + if first < min { + min = first; + } else if first > max { + max = first; + } + break; + } + Some(x) => x + }; + if first < second { + if first < min {min = first;} + if max < second {max = second;} + } else { + if second < min {min = second;} + if max < first {max = first;} + } + } + + MinMax(min, max) + } +} + +/// `MinMaxResult` is an enum returned by `min_max`. See `OrdIterator::min_max` for more detail. +#[deriving(Clone, Eq)] +pub enum MinMaxResult { + /// Empty iterator + NoElements, + + /// Iterator with one element, so the minimum and maximum are the same + OneElement(T), + + /// More than one element in the iterator, the first element is not larger than the second + MinMax(T, T) +} + +impl MinMaxResult { + /// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` has variant + /// `None` if and only if the `MinMaxResult` has variant `NoElements`. Otherwise variant + /// `Some(x,y)` is returned where `x <= y`. If `MinMaxResult` has variant `OneElement(x)`, + /// performing this operation will make one clone of `x`. + /// + /// # Example + /// + /// ```rust + /// use std::iter::{NoElements, OneElement, MinMax, MinMaxResult}; + /// + /// let r: MinMaxResult = NoElements; + /// assert_eq!(r.into_option(), None) + /// + /// let r = OneElement(1); + /// assert_eq!(r.into_option(), Some((1,1))); + /// + /// let r = MinMax(1,2); + /// assert_eq!(r.into_option(), Some((1,2))); + /// ``` + pub fn into_option(self) -> Option<(T,T)> { + match self { + NoElements => None, + OneElement(x) => Some((x.clone(), x)), + MinMax(x, y) => Some((x, y)) + } + } +} + +/// A trait for iterators that are cloneable. +pub trait CloneableIterator { + /// Repeats an iterator endlessly + /// + /// # Example + /// + /// ```rust + /// use std::iter::{CloneableIterator, count}; + /// + /// let a = count(1,1).take(1); + /// let mut cy = a.cycle(); + /// assert_eq!(cy.next(), Some(1)); + /// assert_eq!(cy.next(), Some(1)); + /// ``` + fn cycle(self) -> Cycle; +} + +impl> CloneableIterator for T { + #[inline] + fn cycle(self) -> Cycle { + Cycle{orig: self.clone(), iter: self} + } +} + +/// An iterator that repeats endlessly +#[deriving(Clone)] +pub struct Cycle { + orig: T, + iter: T, +} + +impl> Iterator for Cycle { + #[inline] + fn next(&mut self) -> Option { + match self.iter.next() { + None => { self.iter = self.orig.clone(); self.iter.next() } + y => y + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + // the cycle iterator is either empty or infinite + match self.orig.size_hint() { + sz @ (0, Some(0)) => sz, + (0, _) => (0, None), + _ => (uint::MAX, None) + } + } +} + +impl> RandomAccessIterator for Cycle { + #[inline] + fn indexable(&self) -> uint { + if self.orig.indexable() > 0 { + uint::MAX + } else { + 0 + } + } + + #[inline] + fn idx(&mut self, index: uint) -> Option { + let liter = self.iter.indexable(); + let lorig = self.orig.indexable(); + if lorig == 0 { + None + } else if index < liter { + self.iter.idx(index) + } else { + self.orig.idx((index - liter) % lorig) + } + } +} + +/// An iterator which strings two iterators together +#[deriving(Clone)] +pub struct Chain { + a: T, + b: U, + flag: bool +} + +impl, U: Iterator> Iterator for Chain { + #[inline] + fn next(&mut self) -> Option { + if self.flag { + self.b.next() + } else { + match self.a.next() { + Some(x) => return Some(x), + _ => () + } + self.flag = true; + self.b.next() + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); + + let lower = a_lower.saturating_add(b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => x.checked_add(&y), + _ => None + }; + + (lower, upper) + } +} + +impl, U: DoubleEndedIterator> DoubleEndedIterator +for Chain { + #[inline] + fn next_back(&mut self) -> Option { + match self.b.next_back() { + Some(x) => Some(x), + None => self.a.next_back() + } + } +} + +impl, U: RandomAccessIterator> RandomAccessIterator +for Chain { + #[inline] + fn indexable(&self) -> uint { + let (a, b) = (self.a.indexable(), self.b.indexable()); + a.saturating_add(b) + } + + #[inline] + fn idx(&mut self, index: uint) -> Option { + let len = self.a.indexable(); + if index < len { + self.a.idx(index) + } else { + self.b.idx(index - len) + } + } +} + +/// An iterator which iterates two other iterators simultaneously +#[deriving(Clone)] +pub struct Zip { + a: T, + b: U +} + +impl, U: Iterator> Iterator<(A, B)> for Zip { + #[inline] + fn next(&mut self) -> Option<(A, B)> { + match self.a.next() { + None => None, + Some(x) => match self.b.next() { + None => None, + Some(y) => Some((x, y)) + } + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); + + let lower = cmp::min(a_lower, b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => Some(cmp::min(x,y)), + (Some(x), None) => Some(x), + (None, Some(y)) => Some(y), + (None, None) => None + }; + + (lower, upper) + } +} + +impl, U: ExactSize> DoubleEndedIterator<(A, B)> +for Zip { + #[inline] + fn next_back(&mut self) -> Option<(A, B)> { + let (a_sz, a_upper) = self.a.size_hint(); + let (b_sz, b_upper) = self.b.size_hint(); + assert!(a_upper == Some(a_sz)); + assert!(b_upper == Some(b_sz)); + if a_sz < b_sz { + for _ in range(0, b_sz - a_sz) { self.b.next_back(); } + } else if a_sz > b_sz { + for _ in range(0, a_sz - b_sz) { self.a.next_back(); } + } + let (a_sz, _) = self.a.size_hint(); + let (b_sz, _) = self.b.size_hint(); + assert!(a_sz == b_sz); + match (self.a.next_back(), self.b.next_back()) { + (Some(x), Some(y)) => Some((x, y)), + _ => None + } + } +} + +impl, U: RandomAccessIterator> +RandomAccessIterator<(A, B)> for Zip { + #[inline] + fn indexable(&self) -> uint { + cmp::min(self.a.indexable(), self.b.indexable()) + } + + #[inline] + fn idx(&mut self, index: uint) -> Option<(A, B)> { + match self.a.idx(index) { + None => None, + Some(x) => match self.b.idx(index) { + None => None, + Some(y) => Some((x, y)) + } + } + } +} + +/// An iterator which maps the values of `iter` with `f` +pub struct Map<'a, A, B, T> { + iter: T, + f: |A|: 'a -> B +} + +impl<'a, A, B, T> Map<'a, A, B, T> { + #[inline] + fn do_map(&mut self, elt: Option) -> Option { + match elt { + Some(a) => Some((self.f)(a)), + _ => None + } + } +} + +impl<'a, A, B, T: Iterator> Iterator for Map<'a, A, B, T> { + #[inline] + fn next(&mut self) -> Option { + let next = self.iter.next(); + self.do_map(next) + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.iter.size_hint() + } +} + +impl<'a, A, B, T: DoubleEndedIterator> DoubleEndedIterator for Map<'a, A, B, T> { + #[inline] + fn next_back(&mut self) -> Option { + let next = self.iter.next_back(); + self.do_map(next) + } +} + +impl<'a, A, B, T: RandomAccessIterator> RandomAccessIterator for Map<'a, A, B, T> { + #[inline] + fn indexable(&self) -> uint { + self.iter.indexable() + } + + #[inline] + fn idx(&mut self, index: uint) -> Option { + let elt = self.iter.idx(index); + self.do_map(elt) + } +} + +/// An iterator which filters the elements of `iter` with `predicate` +pub struct Filter<'a, A, T> { + iter: T, + predicate: |&A|: 'a -> bool +} + +impl<'a, A, T: Iterator> Iterator for Filter<'a, A, T> { + #[inline] + fn next(&mut self) -> Option { + for x in self.iter { + if (self.predicate)(&x) { + return Some(x); + } else { + continue + } + } + None + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } +} + +impl<'a, A, T: DoubleEndedIterator> DoubleEndedIterator for Filter<'a, A, T> { + #[inline] + fn next_back(&mut self) -> Option { + loop { + match self.iter.next_back() { + None => return None, + Some(x) => { + if (self.predicate)(&x) { + return Some(x); + } else { + continue + } + } + } + } + } +} + +/// An iterator which uses `f` to both filter and map elements from `iter` +pub struct FilterMap<'a, A, B, T> { + iter: T, + f: |A|: 'a -> Option +} + +impl<'a, A, B, T: Iterator> Iterator for FilterMap<'a, A, B, T> { + #[inline] + fn next(&mut self) -> Option { + for x in self.iter { + match (self.f)(x) { + Some(y) => return Some(y), + None => () + } + } + None + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } +} + +impl<'a, A, B, T: DoubleEndedIterator> DoubleEndedIterator +for FilterMap<'a, A, B, T> { + #[inline] + fn next_back(&mut self) -> Option { + loop { + match self.iter.next_back() { + None => return None, + Some(x) => { + match (self.f)(x) { + Some(y) => return Some(y), + None => () + } + } + } + } + } +} + +/// An iterator which yields the current count and the element during iteration +#[deriving(Clone)] +pub struct Enumerate { + iter: T, + count: uint +} + +impl> Iterator<(uint, A)> for Enumerate { + #[inline] + fn next(&mut self) -> Option<(uint, A)> { + match self.iter.next() { + Some(a) => { + let ret = Some((self.count, a)); + self.count += 1; + ret + } + _ => None + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.iter.size_hint() + } +} + +impl> DoubleEndedIterator<(uint, A)> for Enumerate { + #[inline] + fn next_back(&mut self) -> Option<(uint, A)> { + match self.iter.next_back() { + Some(a) => { + let (lower, upper) = self.iter.size_hint(); + assert!(upper == Some(lower)); + Some((self.count + lower, a)) + } + _ => None + } + } +} + +impl> RandomAccessIterator<(uint, A)> for Enumerate { + #[inline] + fn indexable(&self) -> uint { + self.iter.indexable() + } + + #[inline] + fn idx(&mut self, index: uint) -> Option<(uint, A)> { + match self.iter.idx(index) { + Some(a) => Some((self.count + index, a)), + _ => None, + } + } +} + +/// An iterator with a `peek()` that returns an optional reference to the next element. +pub struct Peekable { + iter: T, + peeked: Option, +} + +impl> Iterator for Peekable { + #[inline] + fn next(&mut self) -> Option { + if self.peeked.is_some() { self.peeked.take() } + else { self.iter.next() } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (lo, hi) = self.iter.size_hint(); + if self.peeked.is_some() { + let lo = lo.saturating_add(1); + let hi = match hi { + Some(x) => x.checked_add(&1), + None => None + }; + (lo, hi) + } else { + (lo, hi) + } + } +} + +impl<'a, A, T: Iterator> Peekable { + /// Return a reference to the next element of the iterator with out advancing it, + /// or None if the iterator is exhausted. + #[inline] + pub fn peek(&'a mut self) -> Option<&'a A> { + if self.peeked.is_none() { + self.peeked = self.iter.next(); + } + match self.peeked { + Some(ref value) => Some(value), + None => None, + } + } + + /// Check whether peekable iterator is empty or not. + #[inline] + pub fn is_empty(&mut self) -> bool { + self.peek().is_none() + } +} + +/// An iterator which rejects elements while `predicate` is true +pub struct SkipWhile<'a, A, T> { + iter: T, + flag: bool, + predicate: |&A|: 'a -> bool +} + +impl<'a, A, T: Iterator> Iterator for SkipWhile<'a, A, T> { + #[inline] + fn next(&mut self) -> Option { + let mut next = self.iter.next(); + if self.flag { + next + } else { + loop { + match next { + Some(x) => { + if (self.predicate)(&x) { + next = self.iter.next(); + continue + } else { + self.flag = true; + return Some(x) + } + } + None => return None + } + } + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } +} + +/// An iterator which only accepts elements while `predicate` is true +pub struct TakeWhile<'a, A, T> { + iter: T, + flag: bool, + predicate: |&A|: 'a -> bool +} + +impl<'a, A, T: Iterator> Iterator for TakeWhile<'a, A, T> { + #[inline] + fn next(&mut self) -> Option { + if self.flag { + None + } else { + match self.iter.next() { + Some(x) => { + if (self.predicate)(&x) { + Some(x) + } else { + self.flag = true; + None + } + } + None => None + } + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } +} + +/// An iterator which skips over `n` elements of `iter`. +#[deriving(Clone)] +pub struct Skip { + iter: T, + n: uint +} + +impl> Iterator for Skip { + #[inline] + fn next(&mut self) -> Option { + let mut next = self.iter.next(); + if self.n == 0 { + next + } else { + let mut n = self.n; + while n > 0 { + n -= 1; + match next { + Some(_) => { + next = self.iter.next(); + continue + } + None => { + self.n = 0; + return None + } + } + } + self.n = 0; + next + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (lower, upper) = self.iter.size_hint(); + + let lower = lower.saturating_sub(self.n); + + let upper = match upper { + Some(x) => Some(x.saturating_sub(self.n)), + None => None + }; + + (lower, upper) + } +} + +impl> RandomAccessIterator for Skip { + #[inline] + fn indexable(&self) -> uint { + self.iter.indexable().saturating_sub(self.n) + } + + #[inline] + fn idx(&mut self, index: uint) -> Option { + if index >= self.indexable() { + None + } else { + self.iter.idx(index + self.n) + } + } +} + +/// An iterator which only iterates over the first `n` iterations of `iter`. +#[deriving(Clone)] +pub struct Take { + iter: T, + n: uint +} + +impl> Iterator for Take { + #[inline] + fn next(&mut self) -> Option { + if self.n != 0 { + self.n -= 1; + self.iter.next() + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (lower, upper) = self.iter.size_hint(); + + let lower = cmp::min(lower, self.n); + + let upper = match upper { + Some(x) if x < self.n => Some(x), + _ => Some(self.n) + }; + + (lower, upper) + } +} + +impl> RandomAccessIterator for Take { + #[inline] + fn indexable(&self) -> uint { + cmp::min(self.iter.indexable(), self.n) + } + + #[inline] + fn idx(&mut self, index: uint) -> Option { + if index >= self.n { + None + } else { + self.iter.idx(index) + } + } +} + + +/// An iterator to maintain state while iterating another iterator +pub struct Scan<'a, A, B, T, St> { + iter: T, + f: |&mut St, A|: 'a -> Option, + + /// The current internal state to be passed to the closure next. + pub state: St, +} + +impl<'a, A, B, T: Iterator, St> Iterator for Scan<'a, A, B, T, St> { + #[inline] + fn next(&mut self) -> Option { + self.iter.next().and_then(|a| (self.f)(&mut self.state, a)) + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the scan function + } +} + +/// An iterator that maps each element to an iterator, +/// and yields the elements of the produced iterators +/// +pub struct FlatMap<'a, A, T, U> { + iter: T, + f: |A|: 'a -> U, + frontiter: Option, + backiter: Option, +} + +impl<'a, A, T: Iterator, B, U: Iterator> Iterator for FlatMap<'a, A, T, U> { + #[inline] + fn next(&mut self) -> Option { + loop { + for inner in self.frontiter.mut_iter() { + for x in *inner { + return Some(x) + } + } + match self.iter.next().map(|x| (self.f)(x)) { + None => return self.backiter.as_mut().and_then(|it| it.next()), + next => self.frontiter = next, + } + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); + let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); + let lo = flo.saturating_add(blo); + match (self.iter.size_hint(), fhi, bhi) { + ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(&b)), + _ => (lo, None) + } + } +} + +impl<'a, + A, T: DoubleEndedIterator, + B, U: DoubleEndedIterator> DoubleEndedIterator + for FlatMap<'a, A, T, U> { + #[inline] + fn next_back(&mut self) -> Option { + loop { + for inner in self.backiter.mut_iter() { + match inner.next_back() { + None => (), + y => return y + } + } + match self.iter.next_back().map(|x| (self.f)(x)) { + None => return self.frontiter.as_mut().and_then(|it| it.next_back()), + next => self.backiter = next, + } + } + } +} + +/// An iterator that yields `None` forever after the underlying iterator +/// yields `None` once. +#[deriving(Clone)] +pub struct Fuse { + iter: T, + done: bool +} + +impl> Iterator for Fuse { + #[inline] + fn next(&mut self) -> Option { + if self.done { + None + } else { + match self.iter.next() { + None => { + self.done = true; + None + } + x => x + } + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + if self.done { + (0, Some(0)) + } else { + self.iter.size_hint() + } + } +} + +impl> DoubleEndedIterator for Fuse { + #[inline] + fn next_back(&mut self) -> Option { + if self.done { + None + } else { + match self.iter.next_back() { + None => { + self.done = true; + None + } + x => x + } + } + } +} + +// Allow RandomAccessIterators to be fused without affecting random-access behavior +impl> RandomAccessIterator for Fuse { + #[inline] + fn indexable(&self) -> uint { + self.iter.indexable() + } + + #[inline] + fn idx(&mut self, index: uint) -> Option { + self.iter.idx(index) + } +} + +impl Fuse { + /// Resets the fuse such that the next call to .next() or .next_back() will + /// call the underlying iterator again even if it previously returned None. + #[inline] + pub fn reset_fuse(&mut self) { + self.done = false + } +} + +/// An iterator that calls a function with a reference to each +/// element before yielding it. +pub struct Inspect<'a, A, T> { + iter: T, + f: |&A|: 'a +} + +impl<'a, A, T> Inspect<'a, A, T> { + #[inline] + fn do_inspect(&mut self, elt: Option) -> Option { + match elt { + Some(ref a) => (self.f)(a), + None => () + } + + elt + } +} + +impl<'a, A, T: Iterator> Iterator for Inspect<'a, A, T> { + #[inline] + fn next(&mut self) -> Option { + let next = self.iter.next(); + self.do_inspect(next) + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.iter.size_hint() + } +} + +impl<'a, A, T: DoubleEndedIterator> DoubleEndedIterator +for Inspect<'a, A, T> { + #[inline] + fn next_back(&mut self) -> Option { + let next = self.iter.next_back(); + self.do_inspect(next) + } +} + +impl<'a, A, T: RandomAccessIterator> RandomAccessIterator +for Inspect<'a, A, T> { + #[inline] + fn indexable(&self) -> uint { + self.iter.indexable() + } + + #[inline] + fn idx(&mut self, index: uint) -> Option { + let element = self.iter.idx(index); + self.do_inspect(element) + } +} + +/// An iterator which just modifies the contained state throughout iteration. +pub struct Unfold<'a, A, St> { + f: |&mut St|: 'a -> Option, + /// Internal state that will be yielded on the next iteration + pub state: St, +} + +impl<'a, A, St> Unfold<'a, A, St> { + /// Creates a new iterator with the specified closure as the "iterator + /// function" and an initial state to eventually pass to the iterator + #[inline] + pub fn new<'a>(initial_state: St, f: |&mut St|: 'a -> Option) + -> Unfold<'a, A, St> { + Unfold { + f: f, + state: initial_state + } + } +} + +impl<'a, A, St> Iterator for Unfold<'a, A, St> { + #[inline] + fn next(&mut self) -> Option { + (self.f)(&mut self.state) + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + // no possible known bounds at this point + (0, None) + } +} + +/// An infinite iterator starting at `start` and advancing by `step` with each +/// iteration +#[deriving(Clone)] +pub struct Counter { + /// The current state the counter is at (next value to be yielded) + state: A, + /// The amount that this iterator is stepping by + step: A, +} + +/// Creates a new counter with the specified start/step +#[inline] +pub fn count(start: A, step: A) -> Counter { + Counter{state: start, step: step} +} + +impl + Clone> Iterator for Counter { + #[inline] + fn next(&mut self) -> Option { + let result = self.state.clone(); + self.state = self.state + self.step; + Some(result) + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + (uint::MAX, None) // Too bad we can't specify an infinite lower bound + } +} + +/// An iterator over the range [start, stop) +#[deriving(Clone)] +pub struct Range { + state: A, + stop: A, + one: A +} + +/// Return an iterator over the range [start, stop) +#[inline] +pub fn range + Ord + Clone + One>(start: A, stop: A) -> Range { + Range{state: start, stop: stop, one: One::one()} +} + +// FIXME: #10414: Unfortunate type bound +impl + Ord + Clone + ToPrimitive> Iterator for Range { + #[inline] + fn next(&mut self) -> Option { + if self.state < self.stop { + let result = self.state.clone(); + self.state = self.state + self.one; + Some(result) + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + // This first checks if the elements are representable as i64. If they aren't, try u64 (to + // handle cases like range(huge, huger)). We don't use uint/int because the difference of + // the i64/u64 might lie within their range. + let bound = match self.state.to_i64() { + Some(a) => { + let sz = self.stop.to_i64().map(|b| b.checked_sub(&a)); + match sz { + Some(Some(bound)) => bound.to_uint(), + _ => None, + } + }, + None => match self.state.to_u64() { + Some(a) => { + let sz = self.stop.to_u64().map(|b| b.checked_sub(&a)); + match sz { + Some(Some(bound)) => bound.to_uint(), + _ => None + } + }, + None => None + } + }; + + match bound { + Some(b) => (b, Some(b)), + // Standard fallback for unbounded/unrepresentable bounds + None => (0, None) + } + } +} + +/// `Int` is required to ensure the range will be the same regardless of +/// the direction it is consumed. +impl DoubleEndedIterator for Range { + #[inline] + fn next_back(&mut self) -> Option { + if self.stop > self.state { + self.stop = self.stop - self.one; + Some(self.stop.clone()) + } else { + None + } + } +} + +/// An iterator over the range [start, stop] +#[deriving(Clone)] +pub struct RangeInclusive { + range: Range, + done: bool, +} + +/// Return an iterator over the range [start, stop] +#[inline] +pub fn range_inclusive + Ord + Clone + One + ToPrimitive>(start: A, stop: A) + -> RangeInclusive { + RangeInclusive{range: range(start, stop), done: false} +} + +impl + Ord + Clone + ToPrimitive> Iterator for RangeInclusive { + #[inline] + fn next(&mut self) -> Option { + match self.range.next() { + Some(x) => Some(x), + None => { + if !self.done && self.range.state == self.range.stop { + self.done = true; + Some(self.range.stop.clone()) + } else { + None + } + } + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (lo, hi) = self.range.size_hint(); + if self.done { + (lo, hi) + } else { + let lo = lo.saturating_add(1); + let hi = match hi { + Some(x) => x.checked_add(&1), + None => None + }; + (lo, hi) + } + } +} + +impl + Int + Ord + Clone + ToPrimitive> DoubleEndedIterator + for RangeInclusive { + #[inline] + fn next_back(&mut self) -> Option { + if self.range.stop > self.range.state { + let result = self.range.stop.clone(); + self.range.stop = self.range.stop - self.range.one; + Some(result) + } else if !self.done && self.range.state == self.range.stop { + self.done = true; + Some(self.range.stop.clone()) + } else { + None + } + } +} + +/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping. +#[deriving(Clone)] +pub struct RangeStep { + state: A, + stop: A, + step: A, + rev: bool, +} + +/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping. +#[inline] +pub fn range_step(start: A, stop: A, step: A) -> RangeStep { + let rev = step < Zero::zero(); + RangeStep{state: start, stop: stop, step: step, rev: rev} +} + +impl Iterator for RangeStep { + #[inline] + fn next(&mut self) -> Option { + if (self.rev && self.state > self.stop) || (!self.rev && self.state < self.stop) { + let result = self.state.clone(); + match self.state.checked_add(&self.step) { + Some(x) => self.state = x, + None => self.state = self.stop.clone() + } + Some(result) + } else { + None + } + } +} + +/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping. +#[deriving(Clone)] +pub struct RangeStepInclusive { + state: A, + stop: A, + step: A, + rev: bool, + done: bool, +} + +/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping. +#[inline] +pub fn range_step_inclusive(start: A, stop: A, + step: A) -> RangeStepInclusive { + let rev = step < Zero::zero(); + RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false} +} + +impl Iterator for RangeStepInclusive { + #[inline] + fn next(&mut self) -> Option { + if !self.done && ((self.rev && self.state >= self.stop) || + (!self.rev && self.state <= self.stop)) { + let result = self.state.clone(); + match self.state.checked_add(&self.step) { + Some(x) => self.state = x, + None => self.done = true + } + Some(result) + } else { + None + } + } +} + +/// An iterator that repeats an element endlessly +#[deriving(Clone)] +pub struct Repeat { + element: A +} + +impl Repeat { + /// Create a new `Repeat` that endlessly repeats the element `elt`. + #[inline] + pub fn new(elt: A) -> Repeat { + Repeat{element: elt} + } +} + +impl Iterator for Repeat { + #[inline] + fn next(&mut self) -> Option { self.idx(0) } + #[inline] + fn size_hint(&self) -> (uint, Option) { (uint::MAX, None) } +} + +impl DoubleEndedIterator for Repeat { + #[inline] + fn next_back(&mut self) -> Option { self.idx(0) } +} + +impl RandomAccessIterator for Repeat { + #[inline] + fn indexable(&self) -> uint { uint::MAX } + #[inline] + fn idx(&mut self, _: uint) -> Option { Some(self.element.clone()) } +} + +/// Functions for lexicographical ordering of sequences. +/// +/// Lexicographical ordering through `<`, `<=`, `>=`, `>` requires +/// that the elements implement both `Eq` and `Ord`. +/// +/// If two sequences are equal up until the point where one ends, +/// the shorter sequence compares less. +pub mod order { + use cmp; + use cmp::{TotalEq, TotalOrd, Ord, Eq}; + use option::{Some, None}; + use super::Iterator; + + /// Compare `a` and `b` for equality using `TotalEq` + pub fn equals>(mut a: T, mut b: T) -> bool { + loop { + match (a.next(), b.next()) { + (None, None) => return true, + (None, _) | (_, None) => return false, + (Some(x), Some(y)) => if x != y { return false }, + } + } + } + + /// Order `a` and `b` lexicographically using `TotalOrd` + pub fn cmp>(mut a: T, mut b: T) -> cmp::Ordering { + loop { + match (a.next(), b.next()) { + (None, None) => return cmp::Equal, + (None, _ ) => return cmp::Less, + (_ , None) => return cmp::Greater, + (Some(x), Some(y)) => match x.cmp(&y) { + cmp::Equal => (), + non_eq => return non_eq, + }, + } + } + } + + /// Compare `a` and `b` for equality (Using partial equality, `Eq`) + pub fn eq>(mut a: T, mut b: T) -> bool { + loop { + match (a.next(), b.next()) { + (None, None) => return true, + (None, _) | (_, None) => return false, + (Some(x), Some(y)) => if !x.eq(&y) { return false }, + } + } + } + + /// Compare `a` and `b` for nonequality (Using partial equality, `Eq`) + pub fn ne>(mut a: T, mut b: T) -> bool { + loop { + match (a.next(), b.next()) { + (None, None) => return false, + (None, _) | (_, None) => return true, + (Some(x), Some(y)) => if x.ne(&y) { return true }, + } + } + } + + /// Return `a` < `b` lexicographically (Using partial order, `Ord`) + pub fn lt>(mut a: T, mut b: T) -> bool { + loop { + match (a.next(), b.next()) { + (None, None) => return false, + (None, _ ) => return true, + (_ , None) => return false, + (Some(x), Some(y)) => if x.ne(&y) { return x.lt(&y) }, + } + } + } + + /// Return `a` <= `b` lexicographically (Using partial order, `Ord`) + pub fn le>(mut a: T, mut b: T) -> bool { + loop { + match (a.next(), b.next()) { + (None, None) => return true, + (None, _ ) => return true, + (_ , None) => return false, + (Some(x), Some(y)) => if x.ne(&y) { return x.le(&y) }, + } + } + } + + /// Return `a` > `b` lexicographically (Using partial order, `Ord`) + pub fn gt>(mut a: T, mut b: T) -> bool { + loop { + match (a.next(), b.next()) { + (None, None) => return false, + (None, _ ) => return false, + (_ , None) => return true, + (Some(x), Some(y)) => if x.ne(&y) { return x.gt(&y) }, + } + } + } + + /// Return `a` >= `b` lexicographically (Using partial order, `Ord`) + pub fn ge>(mut a: T, mut b: T) -> bool { + loop { + match (a.next(), b.next()) { + (None, None) => return true, + (None, _ ) => return false, + (_ , None) => return true, + (Some(x), Some(y)) => if x.ne(&y) { return x.ge(&y) }, + } + } + } + + #[test] + fn test_lt() { + use slice::ImmutableVector; + + let empty: [int, ..0] = []; + let xs = [1,2,3]; + let ys = [1,2,0]; + + assert!(!lt(xs.iter(), ys.iter())); + assert!(!le(xs.iter(), ys.iter())); + assert!( gt(xs.iter(), ys.iter())); + assert!( ge(xs.iter(), ys.iter())); + + assert!( lt(ys.iter(), xs.iter())); + assert!( le(ys.iter(), xs.iter())); + assert!(!gt(ys.iter(), xs.iter())); + assert!(!ge(ys.iter(), xs.iter())); + + assert!( lt(empty.iter(), xs.iter())); + assert!( le(empty.iter(), xs.iter())); + assert!(!gt(empty.iter(), xs.iter())); + assert!(!ge(empty.iter(), xs.iter())); + + // Sequence with NaN + let u = [1.0, 2.0]; + let v = [0.0/0.0, 3.0]; + + assert!(!lt(u.iter(), v.iter())); + assert!(!le(u.iter(), v.iter())); + assert!(!gt(u.iter(), v.iter())); + assert!(!ge(u.iter(), v.iter())); + + let a = [0.0/0.0]; + let b = [1.0]; + let c = [2.0]; + + assert!(lt(a.iter(), b.iter()) == (a[0] < b[0])); + assert!(le(a.iter(), b.iter()) == (a[0] <= b[0])); + assert!(gt(a.iter(), b.iter()) == (a[0] > b[0])); + assert!(ge(a.iter(), b.iter()) == (a[0] >= b[0])); + + assert!(lt(c.iter(), b.iter()) == (c[0] < b[0])); + assert!(le(c.iter(), b.iter()) == (c[0] <= b[0])); + assert!(gt(c.iter(), b.iter()) == (c[0] > b[0])); + assert!(ge(c.iter(), b.iter()) == (c[0] >= b[0])); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use prelude::*; + + use cmp; + use owned::Box; + use uint; + use num; + + #[test] + fn test_counter_from_iter() { + let it = count(0, 5).take(10); + let xs: ~[int] = FromIterator::from_iter(it); + assert_eq!(xs, box [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); + } + + #[test] + fn test_iterator_chain() { + let xs = [0u, 1, 2, 3, 4, 5]; + let ys = [30u, 40, 50, 60]; + let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; + let mut it = xs.iter().chain(ys.iter()); + let mut i = 0; + for &x in it { + assert_eq!(x, expected[i]); + i += 1; + } + assert_eq!(i, expected.len()); + + let ys = count(30u, 10).take(4); + let mut it = xs.iter().map(|&x| x).chain(ys); + let mut i = 0; + for x in it { + assert_eq!(x, expected[i]); + i += 1; + } + assert_eq!(i, expected.len()); + } + + #[test] + fn test_filter_map() { + let mut it = count(0u, 1u).take(10) + .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None }); + assert_eq!(it.collect::<~[uint]>(), box [0*0, 2*2, 4*4, 6*6, 8*8]); + } + + #[test] + fn test_iterator_enumerate() { + let xs = [0u, 1, 2, 3, 4, 5]; + let mut it = xs.iter().enumerate(); + for (i, &x) in it { + assert_eq!(i, x); + } + } + + #[test] + fn test_iterator_peekable() { + let xs = box [0u, 1, 2, 3, 4, 5]; + let mut it = xs.iter().map(|&x|x).peekable(); + assert_eq!(it.peek().unwrap(), &0); + assert_eq!(it.next().unwrap(), 0); + assert_eq!(it.next().unwrap(), 1); + assert_eq!(it.next().unwrap(), 2); + assert_eq!(it.peek().unwrap(), &3); + assert_eq!(it.peek().unwrap(), &3); + assert_eq!(it.next().unwrap(), 3); + assert_eq!(it.next().unwrap(), 4); + assert_eq!(it.peek().unwrap(), &5); + assert_eq!(it.next().unwrap(), 5); + assert!(it.peek().is_none()); + assert!(it.next().is_none()); + } + + #[test] + fn test_iterator_take_while() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [0u, 1, 2, 3, 5, 13]; + let mut it = xs.iter().take_while(|&x| *x < 15u); + let mut i = 0; + for &x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_skip_while() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [15, 16, 17, 19]; + let mut it = xs.iter().skip_while(|&x| *x < 15u); + let mut i = 0; + for &x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_skip() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; + let ys = [13, 15, 16, 17, 19, 20, 30]; + let mut it = xs.iter().skip(5); + let mut i = 0; + for &x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_take() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [0u, 1, 2, 3, 5]; + let mut it = xs.iter().take(5); + let mut i = 0; + for &x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_scan() { + // test the type inference + fn add(old: &mut int, new: &uint) -> Option { + *old += *new as int; + Some(*old as f64) + } + let xs = [0u, 1, 2, 3, 4]; + let ys = [0f64, 1.0, 3.0, 6.0, 10.0]; + + let mut it = xs.iter().scan(0, add); + let mut i = 0; + for x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_flat_map() { + let xs = [0u, 3, 6]; + let ys = [0u, 1, 2, 3, 4, 5, 6, 7, 8]; + let mut it = xs.iter().flat_map(|&x| count(x, 1).take(3)); + let mut i = 0; + for x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_inspect() { + let xs = [1u, 2, 3, 4]; + let mut n = 0; + + let ys = xs.iter() + .map(|&x| x) + .inspect(|_| n += 1) + .collect::<~[uint]>(); + + assert_eq!(n, xs.len()); + assert_eq!(xs.as_slice(), ys.as_slice()); + } + + #[test] + fn test_unfoldr() { + fn count(st: &mut uint) -> Option { + if *st < 10 { + let ret = Some(*st); + *st += 1; + ret + } else { + None + } + } + + let mut it = Unfold::new(0, count); + let mut i = 0; + for counted in it { + assert_eq!(counted, i); + i += 1; + } + assert_eq!(i, 10); + } + + #[test] + fn test_cycle() { + let cycle_len = 3; + let it = count(0u, 1).take(cycle_len).cycle(); + assert_eq!(it.size_hint(), (uint::MAX, None)); + for (i, x) in it.take(100).enumerate() { + assert_eq!(i % cycle_len, x); + } + + let mut it = count(0u, 1).take(0).cycle(); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); + } + + #[test] + fn test_iterator_nth() { + let v = &[0, 1, 2, 3, 4]; + for i in range(0u, v.len()) { + assert_eq!(v.iter().nth(i).unwrap(), &v[i]); + } + } + + #[test] + fn test_iterator_last() { + let v = &[0, 1, 2, 3, 4]; + assert_eq!(v.iter().last().unwrap(), &4); + assert_eq!(v.slice(0, 1).iter().last().unwrap(), &0); + } + + #[test] + fn test_iterator_len() { + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().len(), 4); + assert_eq!(v.slice(0, 10).iter().len(), 10); + assert_eq!(v.slice(0, 0).iter().len(), 0); + } + + #[test] + fn test_iterator_sum() { + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().map(|&x| x).sum(), 6); + assert_eq!(v.iter().map(|&x| x).sum(), 55); + assert_eq!(v.slice(0, 0).iter().map(|&x| x).sum(), 0); + } + + #[test] + fn test_iterator_product() { + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().map(|&x| x).product(), 0); + assert_eq!(v.slice(1, 5).iter().map(|&x| x).product(), 24); + assert_eq!(v.slice(0, 0).iter().map(|&x| x).product(), 1); + } + + #[test] + fn test_iterator_max() { + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().map(|&x| x).max(), Some(3)); + assert_eq!(v.iter().map(|&x| x).max(), Some(10)); + assert_eq!(v.slice(0, 0).iter().map(|&x| x).max(), None); + } + + #[test] + fn test_iterator_min() { + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().map(|&x| x).min(), Some(0)); + assert_eq!(v.iter().map(|&x| x).min(), Some(0)); + assert_eq!(v.slice(0, 0).iter().map(|&x| x).min(), None); + } + + #[test] + fn test_iterator_size_hint() { + let c = count(0, 1); + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let v2 = &[10, 11, 12]; + let vi = v.iter(); + + assert_eq!(c.size_hint(), (uint::MAX, None)); + assert_eq!(vi.size_hint(), (10, Some(10))); + + assert_eq!(c.take(5).size_hint(), (5, Some(5))); + assert_eq!(c.skip(5).size_hint().val1(), None); + assert_eq!(c.take_while(|_| false).size_hint(), (0, None)); + assert_eq!(c.skip_while(|_| false).size_hint(), (0, None)); + assert_eq!(c.enumerate().size_hint(), (uint::MAX, None)); + assert_eq!(c.chain(vi.map(|&i| i)).size_hint(), (uint::MAX, None)); + assert_eq!(c.zip(vi).size_hint(), (10, Some(10))); + assert_eq!(c.scan(0, |_,_| Some(0)).size_hint(), (0, None)); + assert_eq!(c.filter(|_| false).size_hint(), (0, None)); + assert_eq!(c.map(|_| 0).size_hint(), (uint::MAX, None)); + assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None)); + + assert_eq!(vi.take(5).size_hint(), (5, Some(5))); + assert_eq!(vi.take(12).size_hint(), (10, Some(10))); + assert_eq!(vi.skip(3).size_hint(), (7, Some(7))); + assert_eq!(vi.skip(12).size_hint(), (0, Some(0))); + assert_eq!(vi.take_while(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.skip_while(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.enumerate().size_hint(), (10, Some(10))); + assert_eq!(vi.chain(v2.iter()).size_hint(), (13, Some(13))); + assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3))); + assert_eq!(vi.scan(0, |_,_| Some(0)).size_hint(), (0, Some(10))); + assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.map(|i| i+1).size_hint(), (10, Some(10))); + assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10))); + } + + #[test] + fn test_collect() { + let a = box [1, 2, 3, 4, 5]; + let b: ~[int] = a.iter().map(|&x| x).collect(); + assert_eq!(a, b); + } + + #[test] + fn test_all() { + let v: Box<&[int]> = box &[1, 2, 3, 4, 5]; + assert!(v.iter().all(|&x| x < 10)); + assert!(!v.iter().all(|&x| x % 2 == 0)); + assert!(!v.iter().all(|&x| x > 100)); + assert!(v.slice(0, 0).iter().all(|_| fail!())); + } + + #[test] + fn test_any() { + let v: Box<&[int]> = box &[1, 2, 3, 4, 5]; + assert!(v.iter().any(|&x| x < 10)); + assert!(v.iter().any(|&x| x % 2 == 0)); + assert!(!v.iter().any(|&x| x > 100)); + assert!(!v.slice(0, 0).iter().any(|_| fail!())); + } + + #[test] + fn test_find() { + let v: &[int] = &[1, 3, 9, 27, 103, 14, 11]; + assert_eq!(*v.iter().find(|x| *x & 1 == 0).unwrap(), 14); + assert_eq!(*v.iter().find(|x| *x % 3 == 0).unwrap(), 3); + assert!(v.iter().find(|x| *x % 12 == 0).is_none()); + } + + #[test] + fn test_position() { + let v = &[1, 3, 9, 27, 103, 14, 11]; + assert_eq!(v.iter().position(|x| *x & 1 == 0).unwrap(), 5); + assert_eq!(v.iter().position(|x| *x % 3 == 0).unwrap(), 1); + assert!(v.iter().position(|x| *x % 12 == 0).is_none()); + } + + #[test] + fn test_count() { + let xs = &[1, 2, 2, 1, 5, 9, 0, 2]; + assert_eq!(xs.iter().count(|x| *x == 2), 3); + assert_eq!(xs.iter().count(|x| *x == 5), 1); + assert_eq!(xs.iter().count(|x| *x == 95), 0); + } + + #[test] + fn test_max_by() { + let xs: &[int] = &[-3, 0, 1, 5, -10]; + assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10); + } + + #[test] + fn test_min_by() { + let xs: &[int] = &[-3, 0, 1, 5, -10]; + assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0); + } + + #[test] + fn test_by_ref() { + let mut xs = range(0, 10); + // sum the first five values + let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b); + assert_eq!(partial_sum, 10); + assert_eq!(xs.next(), Some(5)); + } + + #[test] + fn test_rev() { + let xs = [2, 4, 6, 8, 10, 12, 14, 16]; + let mut it = xs.iter(); + it.next(); + it.next(); + assert_eq!(it.rev().map(|&x| x).collect::<~[int]>(), box [16, 14, 12, 10, 8, 6]); + } + + #[test] + fn test_double_ended_map() { + let xs = [1, 2, 3, 4, 5, 6]; + let mut it = xs.iter().map(|&x| x * -1); + assert_eq!(it.next(), Some(-1)); + assert_eq!(it.next(), Some(-2)); + assert_eq!(it.next_back(), Some(-6)); + assert_eq!(it.next_back(), Some(-5)); + assert_eq!(it.next(), Some(-3)); + assert_eq!(it.next_back(), Some(-4)); + assert_eq!(it.next(), None); + } + + #[test] + fn test_double_ended_enumerate() { + let xs = [1, 2, 3, 4, 5, 6]; + let mut it = xs.iter().map(|&x| x).enumerate(); + assert_eq!(it.next(), Some((0, 1))); + assert_eq!(it.next(), Some((1, 2))); + assert_eq!(it.next_back(), Some((5, 6))); + assert_eq!(it.next_back(), Some((4, 5))); + assert_eq!(it.next_back(), Some((3, 4))); + assert_eq!(it.next_back(), Some((2, 3))); + assert_eq!(it.next(), None); + } + + #[test] + fn test_double_ended_zip() { + let xs = [1, 2, 3, 4, 5, 6]; + let ys = [1, 2, 3, 7]; + let a = xs.iter().map(|&x| x); + let b = ys.iter().map(|&x| x); + let mut it = a.zip(b); + assert_eq!(it.next(), Some((1, 1))); + assert_eq!(it.next(), Some((2, 2))); + assert_eq!(it.next_back(), Some((4, 7))); + assert_eq!(it.next_back(), Some((3, 3))); + assert_eq!(it.next(), None); + } + + #[test] + fn test_double_ended_filter() { + let xs = [1, 2, 3, 4, 5, 6]; + let mut it = xs.iter().filter(|&x| *x & 1 == 0); + assert_eq!(it.next_back().unwrap(), &6); + assert_eq!(it.next_back().unwrap(), &4); + assert_eq!(it.next().unwrap(), &2); + assert_eq!(it.next_back(), None); + } + + #[test] + fn test_double_ended_filter_map() { + let xs = [1, 2, 3, 4, 5, 6]; + let mut it = xs.iter().filter_map(|&x| if x & 1 == 0 { Some(x * 2) } else { None }); + assert_eq!(it.next_back().unwrap(), 12); + assert_eq!(it.next_back().unwrap(), 8); + assert_eq!(it.next().unwrap(), 4); + assert_eq!(it.next_back(), None); + } + + #[test] + fn test_double_ended_chain() { + let xs = [1, 2, 3, 4, 5]; + let ys = box [7, 9, 11]; + let mut it = xs.iter().chain(ys.iter()).rev(); + assert_eq!(it.next().unwrap(), &11) + assert_eq!(it.next().unwrap(), &9) + assert_eq!(it.next_back().unwrap(), &1) + assert_eq!(it.next_back().unwrap(), &2) + assert_eq!(it.next_back().unwrap(), &3) + assert_eq!(it.next_back().unwrap(), &4) + assert_eq!(it.next_back().unwrap(), &5) + assert_eq!(it.next_back().unwrap(), &7) + assert_eq!(it.next_back(), None) + } + + #[test] + fn test_rposition() { + fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } + fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' } + let v = box [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; + + assert_eq!(v.iter().rposition(f), Some(3u)); + assert!(v.iter().rposition(g).is_none()); + } + + #[test] + #[should_fail] + fn test_rposition_fail() { + let v = [(box 0, @0), (box 0, @0), (box 0, @0), (box 0, @0)]; + let mut i = 0; + v.iter().rposition(|_elt| { + if i == 2 { + fail!() + } + i += 1; + false + }); + } + + + #[cfg(test)] + fn check_randacc_iter>(a: T, len: uint) + { + let mut b = a.clone(); + assert_eq!(len, b.indexable()); + let mut n = 0; + for (i, elt) in a.enumerate() { + assert!(Some(elt) == b.idx(i)); + n += 1; + } + assert_eq!(n, len); + assert!(None == b.idx(n)); + // call recursively to check after picking off an element + if len > 0 { + b.next(); + check_randacc_iter(b, len-1); + } + } + + + #[test] + fn test_double_ended_flat_map() { + let u = [0u,1]; + let v = [5,6,7,8]; + let mut it = u.iter().flat_map(|x| v.slice(*x, v.len()).iter()); + assert_eq!(it.next_back().unwrap(), &8); + assert_eq!(it.next().unwrap(), &5); + assert_eq!(it.next_back().unwrap(), &7); + assert_eq!(it.next_back().unwrap(), &6); + assert_eq!(it.next_back().unwrap(), &8); + assert_eq!(it.next().unwrap(), &6); + assert_eq!(it.next_back().unwrap(), &7); + assert_eq!(it.next_back(), None); + assert_eq!(it.next(), None); + assert_eq!(it.next_back(), None); + } + + #[test] + fn test_random_access_chain() { + let xs = [1, 2, 3, 4, 5]; + let ys = box [7, 9, 11]; + let mut it = xs.iter().chain(ys.iter()); + assert_eq!(it.idx(0).unwrap(), &1); + assert_eq!(it.idx(5).unwrap(), &7); + assert_eq!(it.idx(7).unwrap(), &11); + assert!(it.idx(8).is_none()); + + it.next(); + it.next(); + it.next_back(); + + assert_eq!(it.idx(0).unwrap(), &3); + assert_eq!(it.idx(4).unwrap(), &9); + assert!(it.idx(6).is_none()); + + check_randacc_iter(it, xs.len() + ys.len() - 3); + } + + #[test] + fn test_random_access_enumerate() { + let xs = [1, 2, 3, 4, 5]; + check_randacc_iter(xs.iter().enumerate(), xs.len()); + } + + #[test] + fn test_random_access_rev() { + let xs = [1, 2, 3, 4, 5]; + check_randacc_iter(xs.iter().rev(), xs.len()); + let mut it = xs.iter().rev(); + it.next(); + it.next_back(); + it.next(); + check_randacc_iter(it, xs.len() - 3); + } + + #[test] + fn test_random_access_zip() { + let xs = [1, 2, 3, 4, 5]; + let ys = [7, 9, 11]; + check_randacc_iter(xs.iter().zip(ys.iter()), cmp::min(xs.len(), ys.len())); + } + + #[test] + fn test_random_access_take() { + let xs = [1, 2, 3, 4, 5]; + let empty: &[int] = []; + check_randacc_iter(xs.iter().take(3), 3); + check_randacc_iter(xs.iter().take(20), xs.len()); + check_randacc_iter(xs.iter().take(0), 0); + check_randacc_iter(empty.iter().take(2), 0); + } + + #[test] + fn test_random_access_skip() { + let xs = [1, 2, 3, 4, 5]; + let empty: &[int] = []; + check_randacc_iter(xs.iter().skip(2), xs.len() - 2); + check_randacc_iter(empty.iter().skip(2), 0); + } + + #[test] + fn test_random_access_inspect() { + let xs = [1, 2, 3, 4, 5]; + + // test .map and .inspect that don't implement Clone + let mut it = xs.iter().inspect(|_| {}); + assert_eq!(xs.len(), it.indexable()); + for (i, elt) in xs.iter().enumerate() { + assert_eq!(Some(elt), it.idx(i)); + } + + } + + #[test] + fn test_random_access_map() { + let xs = [1, 2, 3, 4, 5]; + + let mut it = xs.iter().map(|x| *x); + assert_eq!(xs.len(), it.indexable()); + for (i, elt) in xs.iter().enumerate() { + assert_eq!(Some(*elt), it.idx(i)); + } + } + + #[test] + fn test_random_access_cycle() { + let xs = [1, 2, 3, 4, 5]; + let empty: &[int] = []; + check_randacc_iter(xs.iter().cycle().take(27), 27); + check_randacc_iter(empty.iter().cycle(), 0); + } + + #[test] + fn test_double_ended_range() { + assert_eq!(range(11i, 14).rev().collect::<~[int]>(), box [13i, 12, 11]); + for _ in range(10i, 0).rev() { + fail!("unreachable"); + } + + assert_eq!(range(11u, 14).rev().collect::<~[uint]>(), box [13u, 12, 11]); + for _ in range(10u, 0).rev() { + fail!("unreachable"); + } + } + + #[test] + fn test_range() { + /// A mock type to check Range when ToPrimitive returns None + struct Foo; + + impl ToPrimitive for Foo { + fn to_i64(&self) -> Option { None } + fn to_u64(&self) -> Option { None } + } + + impl Add for Foo { + fn add(&self, _: &Foo) -> Foo { + Foo + } + } + + impl Eq for Foo { + fn eq(&self, _: &Foo) -> bool { + true + } + } + + impl Ord for Foo { + fn lt(&self, _: &Foo) -> bool { + false + } + } + + impl Clone for Foo { + fn clone(&self) -> Foo { + Foo + } + } + + impl Mul for Foo { + fn mul(&self, _: &Foo) -> Foo { + Foo + } + } + + impl num::One for Foo { + fn one() -> Foo { + Foo + } + } + + assert_eq!(range(0i, 5).collect::<~[int]>(), box [0i, 1, 2, 3, 4]); + assert_eq!(range(-10i, -1).collect::<~[int]>(), box [-10, -9, -8, -7, -6, -5, -4, -3, -2]); + assert_eq!(range(0i, 5).rev().collect::<~[int]>(), box [4, 3, 2, 1, 0]); + assert_eq!(range(200, -5).collect::<~[int]>(), box []); + assert_eq!(range(200, -5).rev().collect::<~[int]>(), box []); + assert_eq!(range(200, 200).collect::<~[int]>(), box []); + assert_eq!(range(200, 200).rev().collect::<~[int]>(), box []); + + assert_eq!(range(0i, 100).size_hint(), (100, Some(100))); + // this test is only meaningful when sizeof uint < sizeof u64 + assert_eq!(range(uint::MAX - 1, uint::MAX).size_hint(), (1, Some(1))); + assert_eq!(range(-10i, -1).size_hint(), (9, Some(9))); + assert_eq!(range(Foo, Foo).size_hint(), (0, None)); + } + + #[test] + fn test_range_inclusive() { + assert_eq!(range_inclusive(0i, 5).collect::<~[int]>(), box [0i, 1, 2, 3, 4, 5]); + assert_eq!(range_inclusive(0i, 5).rev().collect::<~[int]>(), box [5i, 4, 3, 2, 1, 0]); + assert_eq!(range_inclusive(200, -5).collect::<~[int]>(), box []); + assert_eq!(range_inclusive(200, -5).rev().collect::<~[int]>(), box []); + assert_eq!(range_inclusive(200, 200).collect::<~[int]>(), box [200]); + assert_eq!(range_inclusive(200, 200).rev().collect::<~[int]>(), box [200]); + } + + #[test] + fn test_range_step() { + assert_eq!(range_step(0i, 20, 5).collect::<~[int]>(), box [0, 5, 10, 15]); + assert_eq!(range_step(20i, 0, -5).collect::<~[int]>(), box [20, 15, 10, 5]); + assert_eq!(range_step(20i, 0, -6).collect::<~[int]>(), box [20, 14, 8, 2]); + assert_eq!(range_step(200u8, 255, 50).collect::<~[u8]>(), box [200u8, 250]); + assert_eq!(range_step(200, -5, 1).collect::<~[int]>(), box []); + assert_eq!(range_step(200, 200, 1).collect::<~[int]>(), box []); + } + + #[test] + fn test_range_step_inclusive() { + assert_eq!(range_step_inclusive(0i, 20, 5).collect::<~[int]>(), box [0, 5, 10, 15, 20]); + assert_eq!(range_step_inclusive(20i, 0, -5).collect::<~[int]>(), box [20, 15, 10, 5, 0]); + assert_eq!(range_step_inclusive(20i, 0, -6).collect::<~[int]>(), box [20, 14, 8, 2]); + assert_eq!(range_step_inclusive(200u8, 255, 50).collect::<~[u8]>(), box [200u8, 250]); + assert_eq!(range_step_inclusive(200, -5, 1).collect::<~[int]>(), box []); + assert_eq!(range_step_inclusive(200, 200, 1).collect::<~[int]>(), box [200]); + } + + #[test] + fn test_reverse() { + let mut ys = [1, 2, 3, 4, 5]; + ys.mut_iter().reverse_(); + assert!(ys == [5, 4, 3, 2, 1]); + } + + #[test] + fn test_peekable_is_empty() { + let a = [1]; + let mut it = a.iter().peekable(); + assert!( !it.is_empty() ); + it.next(); + assert!( it.is_empty() ); + } + + #[test] + fn test_min_max() { + let v: [int, ..0] = []; + assert_eq!(v.iter().min_max(), NoElements); + + let v = [1i]; + assert!(v.iter().min_max() == OneElement(&1)); + + let v = [1i, 2, 3, 4, 5]; + assert!(v.iter().min_max() == MinMax(&1, &5)); + + let v = [1i, 2, 3, 4, 5, 6]; + assert!(v.iter().min_max() == MinMax(&1, &6)); + + let v = [1i, 1, 1, 1]; + assert!(v.iter().min_max() == MinMax(&1, &1)); + } + + #[test] + fn test_MinMaxResult() { + let r: MinMaxResult = NoElements; + assert_eq!(r.into_option(), None) + + let r = OneElement(1); + assert_eq!(r.into_option(), Some((1,1))); + + let r = MinMax(1,2); + assert_eq!(r.into_option(), Some((1,2))); + } +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 2a845f32a7e..c4a5254b1eb 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -43,6 +43,7 @@ mod unit; pub mod any; pub mod bool; pub mod finally; +pub mod iter; pub mod option; pub mod raw; pub mod char; diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index a20f0392771..067ce608980 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -489,6 +489,7 @@ use char::Char; use container::Container; use io::MemWriter; use io; +use iter; use iter::{Iterator, range}; use num::Signed; use option::{Option,Some,None}; @@ -1301,5 +1302,18 @@ impl Show for TypeId { } } +impl Show for iter::MinMaxResult { + fn fmt(&self, f: &mut Formatter) -> Result { + match *self { + iter::NoElements => + write!(f.buf, "NoElements"), + iter::OneElement(ref t) => + write!(f.buf, "OneElement({})", *t), + iter::MinMax(ref t1, ref t2) => + write!(f.buf, "MinMax({}, {})", *t1, *t2), + } + } +} + // If you expected tests to be here, look instead at the run-pass/ifmt.rs test, // it's a lot easier than creating all of the rt::Piece structures here. diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs deleted file mode 100644 index 7dc1252fc77..00000000000 --- a/src/libstd/iter.rs +++ /dev/null @@ -1,3090 +0,0 @@ -// 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. - -/*! - -Composable external iterators - -# The `Iterator` trait - -This module defines Rust's core iteration trait. The `Iterator` trait has one -unimplemented method, `next`. All other methods are derived through default -methods to perform operations such as `zip`, `chain`, `enumerate`, and `fold`. - -The goal of this module is to unify iteration across all containers in Rust. -An iterator can be considered as a state machine which is used to track which -element will be yielded next. - -There are various extensions also defined in this module to assist with various -types of iteration, such as the `DoubleEndedIterator` for iterating in reverse, -the `FromIterator` trait for creating a container from an iterator, and much -more. - -## Rust's `for` loop - -The special syntax used by rust's `for` loop is based around the `Iterator` -trait defined in this module. For loops can be viewed as a syntactical expansion -into a `loop`, for example, the `for` loop in this example is essentially -translated to the `loop` below. - -```rust -let values = ~[1, 2, 3]; - -// "Syntactical sugar" taking advantage of an iterator -for &x in values.iter() { - println!("{}", x); -} - -// Rough translation of the iteration without a `for` iterator. -let mut it = values.iter(); -loop { - match it.next() { - Some(&x) => { - println!("{}", x); - } - None => { break } - } -} -``` - -This `for` loop syntax can be applied to any iterator over any type. - -## Iteration protocol and more - -More detailed information about iterators can be found in the [container -guide](http://static.rust-lang.org/doc/master/guide-container.html) with -the rest of the rust manuals. - -*/ - -use cmp; -use num::{Zero, One, CheckedAdd, CheckedSub, Saturating, ToPrimitive, Int}; -use option::{Option, Some, None}; -use ops::{Add, Mul, Sub}; -use cmp::{Eq, Ord, TotalOrd}; -use clone::Clone; -use uint; -use mem; - -/// Conversion from an `Iterator` -pub trait FromIterator { - /// Build a container with elements from an external iterator. - fn from_iter>(iterator: T) -> Self; -} - -/// A type growable from an `Iterator` implementation -pub trait Extendable: FromIterator { - /// Extend a container with the elements yielded by an iterator - fn extend>(&mut self, iterator: T); -} - -/// An interface for dealing with "external iterators". These types of iterators -/// can be resumed at any time as all state is stored internally as opposed to -/// being located on the call stack. -/// -/// The Iterator protocol states that an iterator yields a (potentially-empty, -/// potentially-infinite) sequence of values, and returns `None` to signal that -/// it's finished. The Iterator protocol does not define behavior after `None` -/// is returned. A concrete Iterator implementation may choose to behave however -/// it wishes, either by returning `None` infinitely, or by doing something -/// else. -pub trait Iterator { - /// Advance the iterator and return the next value. Return `None` when the end is reached. - fn next(&mut self) -> Option; - - /// Return a lower bound and upper bound on the remaining length of the iterator. - /// - /// The common use case for the estimate is pre-allocating space to store the results. - #[inline] - fn size_hint(&self) -> (uint, Option) { (0, None) } - - /// Chain this iterator with another, returning a new iterator which will - /// finish iterating over the current iterator, and then it will iterate - /// over the other specified iterator. - /// - /// # Example - /// - /// ```rust - /// let a = [0]; - /// let b = [1]; - /// let mut it = a.iter().chain(b.iter()); - /// assert_eq!(it.next().unwrap(), &0); - /// assert_eq!(it.next().unwrap(), &1); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn chain>(self, other: U) -> Chain { - Chain{a: self, b: other, flag: false} - } - - /// Creates an iterator which iterates over both this and the specified - /// iterators simultaneously, yielding the two elements as pairs. When - /// either iterator returns None, all further invocations of next() will - /// return None. - /// - /// # Example - /// - /// ```rust - /// let a = [0]; - /// let b = [1]; - /// let mut it = a.iter().zip(b.iter()); - /// assert_eq!(it.next().unwrap(), (&0, &1)); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn zip>(self, other: U) -> Zip { - Zip{a: self, b: other} - } - - /// Creates a new iterator which will apply the specified function to each - /// element returned by the first, yielding the mapped element instead. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2]; - /// let mut it = a.iter().map(|&x| 2 * x); - /// assert_eq!(it.next().unwrap(), 2); - /// assert_eq!(it.next().unwrap(), 4); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn map<'r, B>(self, f: |A|: 'r -> B) -> Map<'r, A, B, Self> { - Map{iter: self, f: f} - } - - /// Creates an iterator which applies the predicate to each element returned - /// by this iterator. Only elements which have the predicate evaluate to - /// `true` will be yielded. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2]; - /// let mut it = a.iter().filter(|&x| *x > 1); - /// assert_eq!(it.next().unwrap(), &2); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn filter<'r>(self, predicate: |&A|: 'r -> bool) -> Filter<'r, A, Self> { - Filter{iter: self, predicate: predicate} - } - - /// Creates an iterator which both filters and maps elements. - /// If the specified function returns None, the element is skipped. - /// Otherwise the option is unwrapped and the new value is yielded. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2]; - /// let mut it = a.iter().filter_map(|&x| if x > 1 {Some(2 * x)} else {None}); - /// assert_eq!(it.next().unwrap(), 4); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn filter_map<'r, B>(self, f: |A|: 'r -> Option) -> FilterMap<'r, A, B, Self> { - FilterMap { iter: self, f: f } - } - - /// Creates an iterator which yields a pair of the value returned by this - /// iterator plus the current index of iteration. - /// - /// # Example - /// - /// ```rust - /// let a = [100, 200]; - /// let mut it = a.iter().enumerate(); - /// assert_eq!(it.next().unwrap(), (0, &100)); - /// assert_eq!(it.next().unwrap(), (1, &200)); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn enumerate(self) -> Enumerate { - Enumerate{iter: self, count: 0} - } - - - /// Creates an iterator that has a `.peek()` method - /// that returns an optional reference to the next element. - /// - /// # Example - /// - /// ```rust - /// let xs = [100, 200, 300]; - /// let mut it = xs.iter().map(|x| *x).peekable(); - /// assert_eq!(it.peek().unwrap(), &100); - /// assert_eq!(it.next().unwrap(), 100); - /// assert_eq!(it.next().unwrap(), 200); - /// assert_eq!(it.peek().unwrap(), &300); - /// assert_eq!(it.peek().unwrap(), &300); - /// assert_eq!(it.next().unwrap(), 300); - /// assert!(it.peek().is_none()); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn peekable(self) -> Peekable { - Peekable{iter: self, peeked: None} - } - - /// Creates an iterator which invokes the predicate on elements until it - /// returns false. Once the predicate returns false, all further elements are - /// yielded. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 2, 1]; - /// let mut it = a.iter().skip_while(|&a| *a < 3); - /// assert_eq!(it.next().unwrap(), &3); - /// assert_eq!(it.next().unwrap(), &2); - /// assert_eq!(it.next().unwrap(), &1); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn skip_while<'r>(self, predicate: |&A|: 'r -> bool) -> SkipWhile<'r, A, Self> { - SkipWhile{iter: self, flag: false, predicate: predicate} - } - - /// Creates an iterator which yields elements so long as the predicate - /// returns true. After the predicate returns false for the first time, no - /// further elements will be yielded. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 2, 1]; - /// let mut it = a.iter().take_while(|&a| *a < 3); - /// assert_eq!(it.next().unwrap(), &1); - /// assert_eq!(it.next().unwrap(), &2); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn take_while<'r>(self, predicate: |&A|: 'r -> bool) -> TakeWhile<'r, A, Self> { - TakeWhile{iter: self, flag: false, predicate: predicate} - } - - /// Creates an iterator which skips the first `n` elements of this iterator, - /// and then it yields all further items. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// let mut it = a.iter().skip(3); - /// assert_eq!(it.next().unwrap(), &4); - /// assert_eq!(it.next().unwrap(), &5); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn skip(self, n: uint) -> Skip { - Skip{iter: self, n: n} - } - - /// Creates an iterator which yields the first `n` elements of this - /// iterator, and then it will always return None. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// let mut it = a.iter().take(3); - /// assert_eq!(it.next().unwrap(), &1); - /// assert_eq!(it.next().unwrap(), &2); - /// assert_eq!(it.next().unwrap(), &3); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn take(self, n: uint) -> Take { - Take{iter: self, n: n} - } - - /// Creates a new iterator which behaves in a similar fashion to fold. - /// There is a state which is passed between each iteration and can be - /// mutated as necessary. The yielded values from the closure are yielded - /// from the Scan instance when not None. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// let mut it = a.iter().scan(1, |fac, &x| { - /// *fac = *fac * x; - /// Some(*fac) - /// }); - /// assert_eq!(it.next().unwrap(), 1); - /// assert_eq!(it.next().unwrap(), 2); - /// assert_eq!(it.next().unwrap(), 6); - /// assert_eq!(it.next().unwrap(), 24); - /// assert_eq!(it.next().unwrap(), 120); - /// assert!(it.next().is_none()); - /// ``` - #[inline] - fn scan<'r, St, B>(self, initial_state: St, f: |&mut St, A|: 'r -> Option) - -> Scan<'r, A, B, Self, St> { - Scan{iter: self, f: f, state: initial_state} - } - - /// Creates an iterator that maps each element to an iterator, - /// and yields the elements of the produced iterators - /// - /// # Example - /// - /// ```rust - /// use std::iter::count; - /// - /// let xs = [2u, 3]; - /// let ys = [0u, 1, 0, 1, 2]; - /// let mut it = xs.iter().flat_map(|&x| count(0u, 1).take(x)); - /// // Check that `it` has the same elements as `ys` - /// let mut i = 0; - /// for x in it { - /// assert_eq!(x, ys[i]); - /// i += 1; - /// } - /// ``` - #[inline] - fn flat_map<'r, B, U: Iterator>(self, f: |A|: 'r -> U) - -> FlatMap<'r, A, Self, U> { - FlatMap{iter: self, f: f, frontiter: None, backiter: None } - } - - /// Creates an iterator that yields `None` forever after the underlying - /// iterator yields `None`. Random-access iterator behavior is not - /// affected, only single and double-ended iterator behavior. - /// - /// # Example - /// - /// ```rust - /// fn process>(it: U) -> int { - /// let mut it = it.fuse(); - /// let mut sum = 0; - /// for x in it { - /// if x > 5 { - /// continue; - /// } - /// sum += x; - /// } - /// // did we exhaust the iterator? - /// if it.next().is_none() { - /// sum += 1000; - /// } - /// sum - /// } - /// let x = ~[1,2,3,7,8,9]; - /// assert_eq!(process(x.move_iter()), 1006); - /// ``` - #[inline] - fn fuse(self) -> Fuse { - Fuse{iter: self, done: false} - } - - /// Creates an iterator that calls a function with a reference to each - /// element before yielding it. This is often useful for debugging an - /// iterator pipeline. - /// - /// # Example - /// - /// ```rust - /// use std::iter::AdditiveIterator; - /// - /// let xs = [1u, 4, 2, 3, 8, 9, 6]; - /// let sum = xs.iter() - /// .map(|&x| x) - /// .inspect(|&x| println!("filtering {}", x)) - /// .filter(|&x| x % 2 == 0) - /// .inspect(|&x| println!("{} made it through", x)) - /// .sum(); - /// println!("{}", sum); - /// ``` - #[inline] - fn inspect<'r>(self, f: |&A|: 'r) -> Inspect<'r, A, Self> { - Inspect{iter: self, f: f} - } - - /// Creates a wrapper around a mutable reference to the iterator. - /// - /// This is useful to allow applying iterator adaptors while still - /// retaining ownership of the original iterator value. - /// - /// # Example - /// - /// ```rust - /// let mut xs = range(0, 10); - /// // sum the first five values - /// let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b); - /// assert!(partial_sum == 10); - /// // xs.next() is now `5` - /// assert!(xs.next() == Some(5)); - /// ``` - fn by_ref<'r>(&'r mut self) -> ByRef<'r, Self> { - ByRef{iter: self} - } - - /// Apply a function to each element, or stop iterating if the - /// function returns `false`. - /// - /// # Example - /// - /// ```rust - /// range(0, 5).advance(|x| {print!("{} ", x); true}); - /// ``` - #[inline] - fn advance(&mut self, f: |A| -> bool) -> bool { - loop { - match self.next() { - Some(x) => { - if !f(x) { return false; } - } - None => { return true; } - } - } - } - - /// Loops through the entire iterator, collecting all of the elements into - /// a container implementing `FromIterator`. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// let b: ~[int] = a.iter().map(|&x| x).collect(); - /// assert!(a == b); - /// ``` - #[inline] - fn collect>(&mut self) -> B { - FromIterator::from_iter(self.by_ref()) - } - - /// Loops through `n` iterations, returning the `n`th element of the - /// iterator. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// let mut it = a.iter(); - /// assert!(it.nth(2).unwrap() == &3); - /// assert!(it.nth(2) == None); - /// ``` - #[inline] - fn nth(&mut self, mut n: uint) -> Option { - loop { - match self.next() { - Some(x) => if n == 0 { return Some(x) }, - None => return None - } - n -= 1; - } - } - - /// Loops through the entire iterator, returning the last element of the - /// iterator. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// assert!(a.iter().last().unwrap() == &5); - /// ``` - #[inline] - fn last(&mut self) -> Option { - let mut last = None; - for x in *self { last = Some(x); } - last - } - - /// Performs a fold operation over the entire iterator, returning the - /// eventual state at the end of the iteration. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// assert!(a.iter().fold(0, |a, &b| a + b) == 15); - /// ``` - #[inline] - fn fold(&mut self, init: B, f: |B, A| -> B) -> B { - let mut accum = init; - loop { - match self.next() { - Some(x) => { accum = f(accum, x); } - None => { break; } - } - } - accum - } - - /// Counts the number of elements in this iterator. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// let mut it = a.iter(); - /// assert!(it.len() == 5); - /// assert!(it.len() == 0); - /// ``` - #[inline] - fn len(&mut self) -> uint { - self.fold(0, |cnt, _x| cnt + 1) - } - - /// Tests whether the predicate holds true for all elements in the iterator. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// assert!(a.iter().all(|x| *x > 0)); - /// assert!(!a.iter().all(|x| *x > 2)); - /// ``` - #[inline] - fn all(&mut self, f: |A| -> bool) -> bool { - for x in *self { if !f(x) { return false; } } - true - } - - /// Tests whether any element of an iterator satisfies the specified - /// predicate. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// let mut it = a.iter(); - /// assert!(it.any(|x| *x == 3)); - /// assert!(!it.any(|x| *x == 3)); - /// ``` - #[inline] - fn any(&mut self, f: |A| -> bool) -> bool { - for x in *self { if f(x) { return true; } } - false - } - - /// Return the first element satisfying the specified predicate - #[inline] - fn find(&mut self, predicate: |&A| -> bool) -> Option { - for x in *self { - if predicate(&x) { return Some(x) } - } - None - } - - /// Return the index of the first element satisfying the specified predicate - #[inline] - fn position(&mut self, predicate: |A| -> bool) -> Option { - let mut i = 0; - for x in *self { - if predicate(x) { - return Some(i); - } - i += 1; - } - None - } - - /// Count the number of elements satisfying the specified predicate - #[inline] - fn count(&mut self, predicate: |A| -> bool) -> uint { - let mut i = 0; - for x in *self { - if predicate(x) { i += 1 } - } - i - } - - /// Return the element that gives the maximum value from the - /// specified function. - /// - /// # Example - /// - /// ```rust - /// let xs = [-3i, 0, 1, 5, -10]; - /// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10); - /// ``` - #[inline] - fn max_by(&mut self, f: |&A| -> B) -> Option { - self.fold(None, |max: Option<(A, B)>, x| { - let x_val = f(&x); - match max { - None => Some((x, x_val)), - Some((y, y_val)) => if x_val > y_val { - Some((x, x_val)) - } else { - Some((y, y_val)) - } - } - }).map(|(x, _)| x) - } - - /// Return the element that gives the minimum value from the - /// specified function. - /// - /// # Example - /// - /// ```rust - /// let xs = [-3i, 0, 1, 5, -10]; - /// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0); - /// ``` - #[inline] - fn min_by(&mut self, f: |&A| -> B) -> Option { - self.fold(None, |min: Option<(A, B)>, x| { - let x_val = f(&x); - match min { - None => Some((x, x_val)), - Some((y, y_val)) => if x_val < y_val { - Some((x, x_val)) - } else { - Some((y, y_val)) - } - } - }).map(|(x, _)| x) - } -} - -/// A range iterator able to yield elements from both ends -pub trait DoubleEndedIterator: Iterator { - /// Yield an element from the end of the range, returning `None` if the range is empty. - fn next_back(&mut self) -> Option; - - /// Change the direction of the iterator - /// - /// The flipped iterator swaps the ends on an iterator that can already - /// be iterated from the front and from the back. - /// - /// - /// If the iterator also implements RandomAccessIterator, the flipped - /// iterator is also random access, with the indices starting at the back - /// of the original iterator. - /// - /// Note: Random access with flipped indices still only applies to the first - /// `uint::MAX` elements of the original iterator. - #[inline] - fn rev(self) -> Rev { - Rev{iter: self} - } -} - -/// A double-ended iterator yielding mutable references -pub trait MutableDoubleEndedIterator { - // FIXME: #5898: should be called `reverse` - /// Use an iterator to reverse a container in-place - fn reverse_(&mut self); -} - -impl<'a, A, T: DoubleEndedIterator<&'a mut A>> MutableDoubleEndedIterator for T { - // FIXME: #5898: should be called `reverse` - /// Use an iterator to reverse a container in-place - fn reverse_(&mut self) { - loop { - match (self.next(), self.next_back()) { - (Some(x), Some(y)) => mem::swap(x, y), - _ => break - } - } - } -} - - -/// An object implementing random access indexing by `uint` -/// -/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`. -pub trait RandomAccessIterator: Iterator { - /// Return the number of indexable elements. At most `std::uint::MAX` - /// elements are indexable, even if the iterator represents a longer range. - fn indexable(&self) -> uint; - - /// Return an element at an index - fn idx(&mut self, index: uint) -> Option; -} - -/// An iterator that knows its exact length -/// -/// This trait is a helper for iterators like the vector iterator, so that -/// it can support double-ended enumeration. -/// -/// `Iterator::size_hint` *must* return the exact size of the iterator. -/// Note that the size must fit in `uint`. -pub trait ExactSize : DoubleEndedIterator { - /// Return the index of the last element satisfying the specified predicate - /// - /// If no element matches, None is returned. - #[inline] - fn rposition(&mut self, predicate: |A| -> bool) -> Option { - let (lower, upper) = self.size_hint(); - assert!(upper == Some(lower)); - let mut i = lower; - loop { - match self.next_back() { - None => break, - Some(x) => { - i = match i.checked_sub(&1) { - Some(x) => x, - None => fail!("rposition: incorrect ExactSize") - }; - if predicate(x) { - return Some(i) - } - } - } - } - None - } -} - -// All adaptors that preserve the size of the wrapped iterator are fine -// Adaptors that may overflow in `size_hint` are not, i.e. `Chain`. -impl> ExactSize<(uint, A)> for Enumerate {} -impl<'a, A, T: ExactSize> ExactSize for Inspect<'a, A, T> {} -impl> ExactSize for Rev {} -impl<'a, A, B, T: ExactSize> ExactSize for Map<'a, A, B, T> {} -impl, U: ExactSize> ExactSize<(A, B)> for Zip {} - -/// An double-ended iterator with the direction inverted -#[deriving(Clone)] -pub struct Rev { - iter: T -} - -impl> Iterator for Rev { - #[inline] - fn next(&mut self) -> Option { self.iter.next_back() } - #[inline] - fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } -} - -impl> DoubleEndedIterator for Rev { - #[inline] - fn next_back(&mut self) -> Option { self.iter.next() } -} - -impl + RandomAccessIterator> RandomAccessIterator - for Rev { - #[inline] - fn indexable(&self) -> uint { self.iter.indexable() } - #[inline] - fn idx(&mut self, index: uint) -> Option { - let amt = self.indexable(); - self.iter.idx(amt - index - 1) - } -} - -/// A mutable reference to an iterator -pub struct ByRef<'a, T> { - iter: &'a mut T -} - -impl<'a, A, T: Iterator> Iterator for ByRef<'a, T> { - #[inline] - fn next(&mut self) -> Option { self.iter.next() } - #[inline] - fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } -} - -impl<'a, A, T: DoubleEndedIterator> DoubleEndedIterator for ByRef<'a, T> { - #[inline] - fn next_back(&mut self) -> Option { self.iter.next_back() } -} - -/// A trait for iterators over elements which can be added together -pub trait AdditiveIterator { - /// Iterates over the entire iterator, summing up all the elements - /// - /// # Example - /// - /// ```rust - /// use std::iter::AdditiveIterator; - /// - /// let a = [1, 2, 3, 4, 5]; - /// let mut it = a.iter().map(|&x| x); - /// assert!(it.sum() == 15); - /// ``` - fn sum(&mut self) -> A; -} - -impl + Zero, T: Iterator> AdditiveIterator for T { - #[inline] - fn sum(&mut self) -> A { - let zero: A = Zero::zero(); - self.fold(zero, |s, x| s + x) - } -} - -/// A trait for iterators over elements whose elements can be multiplied -/// together. -pub trait MultiplicativeIterator { - /// Iterates over the entire iterator, multiplying all the elements - /// - /// # Example - /// - /// ```rust - /// use std::iter::{count, MultiplicativeIterator}; - /// - /// fn factorial(n: uint) -> uint { - /// count(1u, 1).take_while(|&i| i <= n).product() - /// } - /// assert!(factorial(0) == 1); - /// assert!(factorial(1) == 1); - /// assert!(factorial(5) == 120); - /// ``` - fn product(&mut self) -> A; -} - -impl + One, T: Iterator> MultiplicativeIterator for T { - #[inline] - fn product(&mut self) -> A { - let one: A = One::one(); - self.fold(one, |p, x| p * x) - } -} - -/// A trait for iterators over elements which can be compared to one another. -/// The type of each element must ascribe to the `Ord` trait. -pub trait OrdIterator { - /// Consumes the entire iterator to return the maximum element. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// assert!(a.iter().max().unwrap() == &5); - /// ``` - fn max(&mut self) -> Option; - - /// Consumes the entire iterator to return the minimum element. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// assert!(a.iter().min().unwrap() == &1); - /// ``` - fn min(&mut self) -> Option; - - /// `min_max` finds the minimum and maximum elements in the iterator. - /// - /// The return type `MinMaxResult` is an enum of three variants: - /// - `NoElements` if the iterator is empty. - /// - `OneElement(x)` if the iterator has exactly one element. - /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two values are equal if and only if - /// there is more than one element in the iterator and all elements are equal. - /// - /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons, - /// and so faster than calling `min` and `max separately which does `2 * n` comparisons. - /// - /// # Example - /// - /// ```rust - /// use std::iter::{NoElements, OneElement, MinMax}; - /// - /// let v: [int, ..0] = []; - /// assert_eq!(v.iter().min_max(), NoElements); - /// - /// let v = [1i]; - /// assert!(v.iter().min_max() == OneElement(&1)); - /// - /// let v = [1i, 2, 3, 4, 5]; - /// assert!(v.iter().min_max() == MinMax(&1, &5)); - /// - /// let v = [1i, 2, 3, 4, 5, 6]; - /// assert!(v.iter().min_max() == MinMax(&1, &6)); - /// - /// let v = [1i, 1, 1, 1]; - /// assert!(v.iter().min_max() == MinMax(&1, &1)); - /// ``` - fn min_max(&mut self) -> MinMaxResult; -} - -impl> OrdIterator for T { - #[inline] - fn max(&mut self) -> Option { - self.fold(None, |max, x| { - match max { - None => Some(x), - Some(y) => Some(cmp::max(x, y)) - } - }) - } - - #[inline] - fn min(&mut self) -> Option { - self.fold(None, |min, x| { - match min { - None => Some(x), - Some(y) => Some(cmp::min(x, y)) - } - }) - } - - fn min_max(&mut self) -> MinMaxResult { - let (mut min, mut max) = match self.next() { - None => return NoElements, - Some(x) => { - match self.next() { - None => return OneElement(x), - Some(y) => if x < y {(x, y)} else {(y,x)} - } - } - }; - - loop { - // `first` and `second` are the two next elements we want to look at. - // We first compare `first` and `second` (#1). The smaller one is then compared to - // current minimum (#2). The larger one is compared to current maximum (#3). This - // way we do 3 comparisons for 2 elements. - let first = match self.next() { - None => break, - Some(x) => x - }; - let second = match self.next() { - None => { - if first < min { - min = first; - } else if first > max { - max = first; - } - break; - } - Some(x) => x - }; - if first < second { - if first < min {min = first;} - if max < second {max = second;} - } else { - if second < min {min = second;} - if max < first {max = first;} - } - } - - MinMax(min, max) - } -} - -/// `MinMaxResult` is an enum returned by `min_max`. See `OrdIterator::min_max` for more detail. -#[deriving(Clone, Eq, Show)] -pub enum MinMaxResult { - /// Empty iterator - NoElements, - - /// Iterator with one element, so the minimum and maximum are the same - OneElement(T), - - /// More than one element in the iterator, the first element is not larger than the second - MinMax(T, T) -} - -impl MinMaxResult { - /// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` has variant - /// `None` if and only if the `MinMaxResult` has variant `NoElements`. Otherwise variant - /// `Some(x,y)` is returned where `x <= y`. If `MinMaxResult` has variant `OneElement(x)`, - /// performing this operation will make one clone of `x`. - /// - /// # Example - /// - /// ```rust - /// use std::iter::{NoElements, OneElement, MinMax, MinMaxResult}; - /// - /// let r: MinMaxResult = NoElements; - /// assert_eq!(r.into_option(), None) - /// - /// let r = OneElement(1); - /// assert_eq!(r.into_option(), Some((1,1))); - /// - /// let r = MinMax(1,2); - /// assert_eq!(r.into_option(), Some((1,2))); - /// ``` - pub fn into_option(self) -> Option<(T,T)> { - match self { - NoElements => None, - OneElement(x) => Some((x.clone(), x)), - MinMax(x, y) => Some((x, y)) - } - } -} - -/// A trait for iterators that are cloneable. -pub trait CloneableIterator { - /// Repeats an iterator endlessly - /// - /// # Example - /// - /// ```rust - /// use std::iter::{CloneableIterator, count}; - /// - /// let a = count(1,1).take(1); - /// let mut cy = a.cycle(); - /// assert_eq!(cy.next(), Some(1)); - /// assert_eq!(cy.next(), Some(1)); - /// ``` - fn cycle(self) -> Cycle; -} - -impl> CloneableIterator for T { - #[inline] - fn cycle(self) -> Cycle { - Cycle{orig: self.clone(), iter: self} - } -} - -/// An iterator that repeats endlessly -#[deriving(Clone)] -pub struct Cycle { - orig: T, - iter: T, -} - -impl> Iterator for Cycle { - #[inline] - fn next(&mut self) -> Option { - match self.iter.next() { - None => { self.iter = self.orig.clone(); self.iter.next() } - y => y - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - // the cycle iterator is either empty or infinite - match self.orig.size_hint() { - sz @ (0, Some(0)) => sz, - (0, _) => (0, None), - _ => (uint::MAX, None) - } - } -} - -impl> RandomAccessIterator for Cycle { - #[inline] - fn indexable(&self) -> uint { - if self.orig.indexable() > 0 { - uint::MAX - } else { - 0 - } - } - - #[inline] - fn idx(&mut self, index: uint) -> Option { - let liter = self.iter.indexable(); - let lorig = self.orig.indexable(); - if lorig == 0 { - None - } else if index < liter { - self.iter.idx(index) - } else { - self.orig.idx((index - liter) % lorig) - } - } -} - -/// An iterator which strings two iterators together -#[deriving(Clone)] -pub struct Chain { - a: T, - b: U, - flag: bool -} - -impl, U: Iterator> Iterator for Chain { - #[inline] - fn next(&mut self) -> Option { - if self.flag { - self.b.next() - } else { - match self.a.next() { - Some(x) => return Some(x), - _ => () - } - self.flag = true; - self.b.next() - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (a_lower, a_upper) = self.a.size_hint(); - let (b_lower, b_upper) = self.b.size_hint(); - - let lower = a_lower.saturating_add(b_lower); - - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => x.checked_add(&y), - _ => None - }; - - (lower, upper) - } -} - -impl, U: DoubleEndedIterator> DoubleEndedIterator -for Chain { - #[inline] - fn next_back(&mut self) -> Option { - match self.b.next_back() { - Some(x) => Some(x), - None => self.a.next_back() - } - } -} - -impl, U: RandomAccessIterator> RandomAccessIterator -for Chain { - #[inline] - fn indexable(&self) -> uint { - let (a, b) = (self.a.indexable(), self.b.indexable()); - a.saturating_add(b) - } - - #[inline] - fn idx(&mut self, index: uint) -> Option { - let len = self.a.indexable(); - if index < len { - self.a.idx(index) - } else { - self.b.idx(index - len) - } - } -} - -/// An iterator which iterates two other iterators simultaneously -#[deriving(Clone)] -pub struct Zip { - a: T, - b: U -} - -impl, U: Iterator> Iterator<(A, B)> for Zip { - #[inline] - fn next(&mut self) -> Option<(A, B)> { - match self.a.next() { - None => None, - Some(x) => match self.b.next() { - None => None, - Some(y) => Some((x, y)) - } - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (a_lower, a_upper) = self.a.size_hint(); - let (b_lower, b_upper) = self.b.size_hint(); - - let lower = cmp::min(a_lower, b_lower); - - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => Some(cmp::min(x,y)), - (Some(x), None) => Some(x), - (None, Some(y)) => Some(y), - (None, None) => None - }; - - (lower, upper) - } -} - -impl, U: ExactSize> DoubleEndedIterator<(A, B)> -for Zip { - #[inline] - fn next_back(&mut self) -> Option<(A, B)> { - let (a_sz, a_upper) = self.a.size_hint(); - let (b_sz, b_upper) = self.b.size_hint(); - assert!(a_upper == Some(a_sz)); - assert!(b_upper == Some(b_sz)); - if a_sz < b_sz { - for _ in range(0, b_sz - a_sz) { self.b.next_back(); } - } else if a_sz > b_sz { - for _ in range(0, a_sz - b_sz) { self.a.next_back(); } - } - let (a_sz, _) = self.a.size_hint(); - let (b_sz, _) = self.b.size_hint(); - assert!(a_sz == b_sz); - match (self.a.next_back(), self.b.next_back()) { - (Some(x), Some(y)) => Some((x, y)), - _ => None - } - } -} - -impl, U: RandomAccessIterator> -RandomAccessIterator<(A, B)> for Zip { - #[inline] - fn indexable(&self) -> uint { - cmp::min(self.a.indexable(), self.b.indexable()) - } - - #[inline] - fn idx(&mut self, index: uint) -> Option<(A, B)> { - match self.a.idx(index) { - None => None, - Some(x) => match self.b.idx(index) { - None => None, - Some(y) => Some((x, y)) - } - } - } -} - -/// An iterator which maps the values of `iter` with `f` -pub struct Map<'a, A, B, T> { - iter: T, - f: |A|: 'a -> B -} - -impl<'a, A, B, T> Map<'a, A, B, T> { - #[inline] - fn do_map(&mut self, elt: Option) -> Option { - match elt { - Some(a) => Some((self.f)(a)), - _ => None - } - } -} - -impl<'a, A, B, T: Iterator> Iterator for Map<'a, A, B, T> { - #[inline] - fn next(&mut self) -> Option { - let next = self.iter.next(); - self.do_map(next) - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - self.iter.size_hint() - } -} - -impl<'a, A, B, T: DoubleEndedIterator> DoubleEndedIterator for Map<'a, A, B, T> { - #[inline] - fn next_back(&mut self) -> Option { - let next = self.iter.next_back(); - self.do_map(next) - } -} - -impl<'a, A, B, T: RandomAccessIterator> RandomAccessIterator for Map<'a, A, B, T> { - #[inline] - fn indexable(&self) -> uint { - self.iter.indexable() - } - - #[inline] - fn idx(&mut self, index: uint) -> Option { - let elt = self.iter.idx(index); - self.do_map(elt) - } -} - -/// An iterator which filters the elements of `iter` with `predicate` -pub struct Filter<'a, A, T> { - iter: T, - predicate: |&A|: 'a -> bool -} - -impl<'a, A, T: Iterator> Iterator for Filter<'a, A, T> { - #[inline] - fn next(&mut self) -> Option { - for x in self.iter { - if (self.predicate)(&x) { - return Some(x); - } else { - continue - } - } - None - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate - } -} - -impl<'a, A, T: DoubleEndedIterator> DoubleEndedIterator for Filter<'a, A, T> { - #[inline] - fn next_back(&mut self) -> Option { - loop { - match self.iter.next_back() { - None => return None, - Some(x) => { - if (self.predicate)(&x) { - return Some(x); - } else { - continue - } - } - } - } - } -} - -/// An iterator which uses `f` to both filter and map elements from `iter` -pub struct FilterMap<'a, A, B, T> { - iter: T, - f: |A|: 'a -> Option -} - -impl<'a, A, B, T: Iterator> Iterator for FilterMap<'a, A, B, T> { - #[inline] - fn next(&mut self) -> Option { - for x in self.iter { - match (self.f)(x) { - Some(y) => return Some(y), - None => () - } - } - None - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate - } -} - -impl<'a, A, B, T: DoubleEndedIterator> DoubleEndedIterator -for FilterMap<'a, A, B, T> { - #[inline] - fn next_back(&mut self) -> Option { - loop { - match self.iter.next_back() { - None => return None, - Some(x) => { - match (self.f)(x) { - Some(y) => return Some(y), - None => () - } - } - } - } - } -} - -/// An iterator which yields the current count and the element during iteration -#[deriving(Clone)] -pub struct Enumerate { - iter: T, - count: uint -} - -impl> Iterator<(uint, A)> for Enumerate { - #[inline] - fn next(&mut self) -> Option<(uint, A)> { - match self.iter.next() { - Some(a) => { - let ret = Some((self.count, a)); - self.count += 1; - ret - } - _ => None - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - self.iter.size_hint() - } -} - -impl> DoubleEndedIterator<(uint, A)> for Enumerate { - #[inline] - fn next_back(&mut self) -> Option<(uint, A)> { - match self.iter.next_back() { - Some(a) => { - let (lower, upper) = self.iter.size_hint(); - assert!(upper == Some(lower)); - Some((self.count + lower, a)) - } - _ => None - } - } -} - -impl> RandomAccessIterator<(uint, A)> for Enumerate { - #[inline] - fn indexable(&self) -> uint { - self.iter.indexable() - } - - #[inline] - fn idx(&mut self, index: uint) -> Option<(uint, A)> { - match self.iter.idx(index) { - Some(a) => Some((self.count + index, a)), - _ => None, - } - } -} - -/// An iterator with a `peek()` that returns an optional reference to the next element. -pub struct Peekable { - iter: T, - peeked: Option, -} - -impl> Iterator for Peekable { - #[inline] - fn next(&mut self) -> Option { - if self.peeked.is_some() { self.peeked.take() } - else { self.iter.next() } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (lo, hi) = self.iter.size_hint(); - if self.peeked.is_some() { - let lo = lo.saturating_add(1); - let hi = match hi { - Some(x) => x.checked_add(&1), - None => None - }; - (lo, hi) - } else { - (lo, hi) - } - } -} - -impl<'a, A, T: Iterator> Peekable { - /// Return a reference to the next element of the iterator with out advancing it, - /// or None if the iterator is exhausted. - #[inline] - pub fn peek(&'a mut self) -> Option<&'a A> { - if self.peeked.is_none() { - self.peeked = self.iter.next(); - } - match self.peeked { - Some(ref value) => Some(value), - None => None, - } - } - - /// Check whether peekable iterator is empty or not. - #[inline] - pub fn is_empty(&mut self) -> bool { - self.peek().is_none() - } -} - -/// An iterator which rejects elements while `predicate` is true -pub struct SkipWhile<'a, A, T> { - iter: T, - flag: bool, - predicate: |&A|: 'a -> bool -} - -impl<'a, A, T: Iterator> Iterator for SkipWhile<'a, A, T> { - #[inline] - fn next(&mut self) -> Option { - let mut next = self.iter.next(); - if self.flag { - next - } else { - loop { - match next { - Some(x) => { - if (self.predicate)(&x) { - next = self.iter.next(); - continue - } else { - self.flag = true; - return Some(x) - } - } - None => return None - } - } - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate - } -} - -/// An iterator which only accepts elements while `predicate` is true -pub struct TakeWhile<'a, A, T> { - iter: T, - flag: bool, - predicate: |&A|: 'a -> bool -} - -impl<'a, A, T: Iterator> Iterator for TakeWhile<'a, A, T> { - #[inline] - fn next(&mut self) -> Option { - if self.flag { - None - } else { - match self.iter.next() { - Some(x) => { - if (self.predicate)(&x) { - Some(x) - } else { - self.flag = true; - None - } - } - None => None - } - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate - } -} - -/// An iterator which skips over `n` elements of `iter`. -#[deriving(Clone)] -pub struct Skip { - iter: T, - n: uint -} - -impl> Iterator for Skip { - #[inline] - fn next(&mut self) -> Option { - let mut next = self.iter.next(); - if self.n == 0 { - next - } else { - let mut n = self.n; - while n > 0 { - n -= 1; - match next { - Some(_) => { - next = self.iter.next(); - continue - } - None => { - self.n = 0; - return None - } - } - } - self.n = 0; - next - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (lower, upper) = self.iter.size_hint(); - - let lower = lower.saturating_sub(self.n); - - let upper = match upper { - Some(x) => Some(x.saturating_sub(self.n)), - None => None - }; - - (lower, upper) - } -} - -impl> RandomAccessIterator for Skip { - #[inline] - fn indexable(&self) -> uint { - self.iter.indexable().saturating_sub(self.n) - } - - #[inline] - fn idx(&mut self, index: uint) -> Option { - if index >= self.indexable() { - None - } else { - self.iter.idx(index + self.n) - } - } -} - -/// An iterator which only iterates over the first `n` iterations of `iter`. -#[deriving(Clone)] -pub struct Take { - iter: T, - n: uint -} - -impl> Iterator for Take { - #[inline] - fn next(&mut self) -> Option { - if self.n != 0 { - self.n -= 1; - self.iter.next() - } else { - None - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (lower, upper) = self.iter.size_hint(); - - let lower = cmp::min(lower, self.n); - - let upper = match upper { - Some(x) if x < self.n => Some(x), - _ => Some(self.n) - }; - - (lower, upper) - } -} - -impl> RandomAccessIterator for Take { - #[inline] - fn indexable(&self) -> uint { - cmp::min(self.iter.indexable(), self.n) - } - - #[inline] - fn idx(&mut self, index: uint) -> Option { - if index >= self.n { - None - } else { - self.iter.idx(index) - } - } -} - - -/// An iterator to maintain state while iterating another iterator -pub struct Scan<'a, A, B, T, St> { - iter: T, - f: |&mut St, A|: 'a -> Option, - - /// The current internal state to be passed to the closure next. - pub state: St, -} - -impl<'a, A, B, T: Iterator, St> Iterator for Scan<'a, A, B, T, St> { - #[inline] - fn next(&mut self) -> Option { - self.iter.next().and_then(|a| (self.f)(&mut self.state, a)) - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the scan function - } -} - -/// An iterator that maps each element to an iterator, -/// and yields the elements of the produced iterators -/// -pub struct FlatMap<'a, A, T, U> { - iter: T, - f: |A|: 'a -> U, - frontiter: Option, - backiter: Option, -} - -impl<'a, A, T: Iterator, B, U: Iterator> Iterator for FlatMap<'a, A, T, U> { - #[inline] - fn next(&mut self) -> Option { - loop { - for inner in self.frontiter.mut_iter() { - for x in *inner { - return Some(x) - } - } - match self.iter.next().map(|x| (self.f)(x)) { - None => return self.backiter.as_mut().and_then(|it| it.next()), - next => self.frontiter = next, - } - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); - let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); - let lo = flo.saturating_add(blo); - match (self.iter.size_hint(), fhi, bhi) { - ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(&b)), - _ => (lo, None) - } - } -} - -impl<'a, - A, T: DoubleEndedIterator, - B, U: DoubleEndedIterator> DoubleEndedIterator - for FlatMap<'a, A, T, U> { - #[inline] - fn next_back(&mut self) -> Option { - loop { - for inner in self.backiter.mut_iter() { - match inner.next_back() { - None => (), - y => return y - } - } - match self.iter.next_back().map(|x| (self.f)(x)) { - None => return self.frontiter.as_mut().and_then(|it| it.next_back()), - next => self.backiter = next, - } - } - } -} - -/// An iterator that yields `None` forever after the underlying iterator -/// yields `None` once. -#[deriving(Clone)] -pub struct Fuse { - iter: T, - done: bool -} - -impl> Iterator for Fuse { - #[inline] - fn next(&mut self) -> Option { - if self.done { - None - } else { - match self.iter.next() { - None => { - self.done = true; - None - } - x => x - } - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - if self.done { - (0, Some(0)) - } else { - self.iter.size_hint() - } - } -} - -impl> DoubleEndedIterator for Fuse { - #[inline] - fn next_back(&mut self) -> Option { - if self.done { - None - } else { - match self.iter.next_back() { - None => { - self.done = true; - None - } - x => x - } - } - } -} - -// Allow RandomAccessIterators to be fused without affecting random-access behavior -impl> RandomAccessIterator for Fuse { - #[inline] - fn indexable(&self) -> uint { - self.iter.indexable() - } - - #[inline] - fn idx(&mut self, index: uint) -> Option { - self.iter.idx(index) - } -} - -impl Fuse { - /// Resets the fuse such that the next call to .next() or .next_back() will - /// call the underlying iterator again even if it previously returned None. - #[inline] - pub fn reset_fuse(&mut self) { - self.done = false - } -} - -/// An iterator that calls a function with a reference to each -/// element before yielding it. -pub struct Inspect<'a, A, T> { - iter: T, - f: |&A|: 'a -} - -impl<'a, A, T> Inspect<'a, A, T> { - #[inline] - fn do_inspect(&mut self, elt: Option) -> Option { - match elt { - Some(ref a) => (self.f)(a), - None => () - } - - elt - } -} - -impl<'a, A, T: Iterator> Iterator for Inspect<'a, A, T> { - #[inline] - fn next(&mut self) -> Option { - let next = self.iter.next(); - self.do_inspect(next) - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - self.iter.size_hint() - } -} - -impl<'a, A, T: DoubleEndedIterator> DoubleEndedIterator -for Inspect<'a, A, T> { - #[inline] - fn next_back(&mut self) -> Option { - let next = self.iter.next_back(); - self.do_inspect(next) - } -} - -impl<'a, A, T: RandomAccessIterator> RandomAccessIterator -for Inspect<'a, A, T> { - #[inline] - fn indexable(&self) -> uint { - self.iter.indexable() - } - - #[inline] - fn idx(&mut self, index: uint) -> Option { - let element = self.iter.idx(index); - self.do_inspect(element) - } -} - -/// An iterator which just modifies the contained state throughout iteration. -pub struct Unfold<'a, A, St> { - f: |&mut St|: 'a -> Option, - /// Internal state that will be yielded on the next iteration - pub state: St, -} - -impl<'a, A, St> Unfold<'a, A, St> { - /// Creates a new iterator with the specified closure as the "iterator - /// function" and an initial state to eventually pass to the iterator - #[inline] - pub fn new<'a>(initial_state: St, f: |&mut St|: 'a -> Option) - -> Unfold<'a, A, St> { - Unfold { - f: f, - state: initial_state - } - } -} - -impl<'a, A, St> Iterator for Unfold<'a, A, St> { - #[inline] - fn next(&mut self) -> Option { - (self.f)(&mut self.state) - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - // no possible known bounds at this point - (0, None) - } -} - -/// An infinite iterator starting at `start` and advancing by `step` with each -/// iteration -#[deriving(Clone)] -pub struct Counter { - /// The current state the counter is at (next value to be yielded) - state: A, - /// The amount that this iterator is stepping by - step: A, -} - -/// Creates a new counter with the specified start/step -#[inline] -pub fn count(start: A, step: A) -> Counter { - Counter{state: start, step: step} -} - -impl + Clone> Iterator for Counter { - #[inline] - fn next(&mut self) -> Option { - let result = self.state.clone(); - self.state = self.state + self.step; - Some(result) - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - (uint::MAX, None) // Too bad we can't specify an infinite lower bound - } -} - -/// An iterator over the range [start, stop) -#[deriving(Clone)] -pub struct Range { - state: A, - stop: A, - one: A -} - -/// Return an iterator over the range [start, stop) -#[inline] -pub fn range + Ord + Clone + One>(start: A, stop: A) -> Range { - Range{state: start, stop: stop, one: One::one()} -} - -// FIXME: #10414: Unfortunate type bound -impl + Ord + Clone + ToPrimitive> Iterator for Range { - #[inline] - fn next(&mut self) -> Option { - if self.state < self.stop { - let result = self.state.clone(); - self.state = self.state + self.one; - Some(result) - } else { - None - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - // This first checks if the elements are representable as i64. If they aren't, try u64 (to - // handle cases like range(huge, huger)). We don't use uint/int because the difference of - // the i64/u64 might lie within their range. - let bound = match self.state.to_i64() { - Some(a) => { - let sz = self.stop.to_i64().map(|b| b.checked_sub(&a)); - match sz { - Some(Some(bound)) => bound.to_uint(), - _ => None, - } - }, - None => match self.state.to_u64() { - Some(a) => { - let sz = self.stop.to_u64().map(|b| b.checked_sub(&a)); - match sz { - Some(Some(bound)) => bound.to_uint(), - _ => None - } - }, - None => None - } - }; - - match bound { - Some(b) => (b, Some(b)), - // Standard fallback for unbounded/unrepresentable bounds - None => (0, None) - } - } -} - -/// `Int` is required to ensure the range will be the same regardless of -/// the direction it is consumed. -impl DoubleEndedIterator for Range { - #[inline] - fn next_back(&mut self) -> Option { - if self.stop > self.state { - self.stop = self.stop - self.one; - Some(self.stop.clone()) - } else { - None - } - } -} - -/// An iterator over the range [start, stop] -#[deriving(Clone)] -pub struct RangeInclusive { - range: Range, - done: bool, -} - -/// Return an iterator over the range [start, stop] -#[inline] -pub fn range_inclusive + Ord + Clone + One + ToPrimitive>(start: A, stop: A) - -> RangeInclusive { - RangeInclusive{range: range(start, stop), done: false} -} - -impl + Ord + Clone + ToPrimitive> Iterator for RangeInclusive { - #[inline] - fn next(&mut self) -> Option { - match self.range.next() { - Some(x) => Some(x), - None => { - if !self.done && self.range.state == self.range.stop { - self.done = true; - Some(self.range.stop.clone()) - } else { - None - } - } - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let (lo, hi) = self.range.size_hint(); - if self.done { - (lo, hi) - } else { - let lo = lo.saturating_add(1); - let hi = match hi { - Some(x) => x.checked_add(&1), - None => None - }; - (lo, hi) - } - } -} - -impl + Int + Ord + Clone + ToPrimitive> DoubleEndedIterator - for RangeInclusive { - #[inline] - fn next_back(&mut self) -> Option { - if self.range.stop > self.range.state { - let result = self.range.stop.clone(); - self.range.stop = self.range.stop - self.range.one; - Some(result) - } else if !self.done && self.range.state == self.range.stop { - self.done = true; - Some(self.range.stop.clone()) - } else { - None - } - } -} - -/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping. -#[deriving(Clone)] -pub struct RangeStep { - state: A, - stop: A, - step: A, - rev: bool, -} - -/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping. -#[inline] -pub fn range_step(start: A, stop: A, step: A) -> RangeStep { - let rev = step < Zero::zero(); - RangeStep{state: start, stop: stop, step: step, rev: rev} -} - -impl Iterator for RangeStep { - #[inline] - fn next(&mut self) -> Option { - if (self.rev && self.state > self.stop) || (!self.rev && self.state < self.stop) { - let result = self.state.clone(); - match self.state.checked_add(&self.step) { - Some(x) => self.state = x, - None => self.state = self.stop.clone() - } - Some(result) - } else { - None - } - } -} - -/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping. -#[deriving(Clone)] -pub struct RangeStepInclusive { - state: A, - stop: A, - step: A, - rev: bool, - done: bool, -} - -/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping. -#[inline] -pub fn range_step_inclusive(start: A, stop: A, - step: A) -> RangeStepInclusive { - let rev = step < Zero::zero(); - RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false} -} - -impl Iterator for RangeStepInclusive { - #[inline] - fn next(&mut self) -> Option { - if !self.done && ((self.rev && self.state >= self.stop) || - (!self.rev && self.state <= self.stop)) { - let result = self.state.clone(); - match self.state.checked_add(&self.step) { - Some(x) => self.state = x, - None => self.done = true - } - Some(result) - } else { - None - } - } -} - -/// An iterator that repeats an element endlessly -#[deriving(Clone)] -pub struct Repeat { - element: A -} - -impl Repeat { - /// Create a new `Repeat` that endlessly repeats the element `elt`. - #[inline] - pub fn new(elt: A) -> Repeat { - Repeat{element: elt} - } -} - -impl Iterator for Repeat { - #[inline] - fn next(&mut self) -> Option { self.idx(0) } - #[inline] - fn size_hint(&self) -> (uint, Option) { (uint::MAX, None) } -} - -impl DoubleEndedIterator for Repeat { - #[inline] - fn next_back(&mut self) -> Option { self.idx(0) } -} - -impl RandomAccessIterator for Repeat { - #[inline] - fn indexable(&self) -> uint { uint::MAX } - #[inline] - fn idx(&mut self, _: uint) -> Option { Some(self.element.clone()) } -} - -/// Functions for lexicographical ordering of sequences. -/// -/// Lexicographical ordering through `<`, `<=`, `>=`, `>` requires -/// that the elements implement both `Eq` and `Ord`. -/// -/// If two sequences are equal up until the point where one ends, -/// the shorter sequence compares less. -pub mod order { - use cmp; - use cmp::{TotalEq, TotalOrd, Ord, Eq}; - use option::{Some, None}; - use super::Iterator; - - /// Compare `a` and `b` for equality using `TotalEq` - pub fn equals>(mut a: T, mut b: T) -> bool { - loop { - match (a.next(), b.next()) { - (None, None) => return true, - (None, _) | (_, None) => return false, - (Some(x), Some(y)) => if x != y { return false }, - } - } - } - - /// Order `a` and `b` lexicographically using `TotalOrd` - pub fn cmp>(mut a: T, mut b: T) -> cmp::Ordering { - loop { - match (a.next(), b.next()) { - (None, None) => return cmp::Equal, - (None, _ ) => return cmp::Less, - (_ , None) => return cmp::Greater, - (Some(x), Some(y)) => match x.cmp(&y) { - cmp::Equal => (), - non_eq => return non_eq, - }, - } - } - } - - /// Compare `a` and `b` for equality (Using partial equality, `Eq`) - pub fn eq>(mut a: T, mut b: T) -> bool { - loop { - match (a.next(), b.next()) { - (None, None) => return true, - (None, _) | (_, None) => return false, - (Some(x), Some(y)) => if !x.eq(&y) { return false }, - } - } - } - - /// Compare `a` and `b` for nonequality (Using partial equality, `Eq`) - pub fn ne>(mut a: T, mut b: T) -> bool { - loop { - match (a.next(), b.next()) { - (None, None) => return false, - (None, _) | (_, None) => return true, - (Some(x), Some(y)) => if x.ne(&y) { return true }, - } - } - } - - /// Return `a` < `b` lexicographically (Using partial order, `Ord`) - pub fn lt>(mut a: T, mut b: T) -> bool { - loop { - match (a.next(), b.next()) { - (None, None) => return false, - (None, _ ) => return true, - (_ , None) => return false, - (Some(x), Some(y)) => if x.ne(&y) { return x.lt(&y) }, - } - } - } - - /// Return `a` <= `b` lexicographically (Using partial order, `Ord`) - pub fn le>(mut a: T, mut b: T) -> bool { - loop { - match (a.next(), b.next()) { - (None, None) => return true, - (None, _ ) => return true, - (_ , None) => return false, - (Some(x), Some(y)) => if x.ne(&y) { return x.le(&y) }, - } - } - } - - /// Return `a` > `b` lexicographically (Using partial order, `Ord`) - pub fn gt>(mut a: T, mut b: T) -> bool { - loop { - match (a.next(), b.next()) { - (None, None) => return false, - (None, _ ) => return false, - (_ , None) => return true, - (Some(x), Some(y)) => if x.ne(&y) { return x.gt(&y) }, - } - } - } - - /// Return `a` >= `b` lexicographically (Using partial order, `Ord`) - pub fn ge>(mut a: T, mut b: T) -> bool { - loop { - match (a.next(), b.next()) { - (None, None) => return true, - (None, _ ) => return false, - (_ , None) => return true, - (Some(x), Some(y)) => if x.ne(&y) { return x.ge(&y) }, - } - } - } - - #[test] - fn test_lt() { - use slice::ImmutableVector; - - let empty: [int, ..0] = []; - let xs = [1,2,3]; - let ys = [1,2,0]; - - assert!(!lt(xs.iter(), ys.iter())); - assert!(!le(xs.iter(), ys.iter())); - assert!( gt(xs.iter(), ys.iter())); - assert!( ge(xs.iter(), ys.iter())); - - assert!( lt(ys.iter(), xs.iter())); - assert!( le(ys.iter(), xs.iter())); - assert!(!gt(ys.iter(), xs.iter())); - assert!(!ge(ys.iter(), xs.iter())); - - assert!( lt(empty.iter(), xs.iter())); - assert!( le(empty.iter(), xs.iter())); - assert!(!gt(empty.iter(), xs.iter())); - assert!(!ge(empty.iter(), xs.iter())); - - // Sequence with NaN - let u = [1.0, 2.0]; - let v = [0.0/0.0, 3.0]; - - assert!(!lt(u.iter(), v.iter())); - assert!(!le(u.iter(), v.iter())); - assert!(!gt(u.iter(), v.iter())); - assert!(!ge(u.iter(), v.iter())); - - let a = [0.0/0.0]; - let b = [1.0]; - let c = [2.0]; - - assert!(lt(a.iter(), b.iter()) == (a[0] < b[0])); - assert!(le(a.iter(), b.iter()) == (a[0] <= b[0])); - assert!(gt(a.iter(), b.iter()) == (a[0] > b[0])); - assert!(ge(a.iter(), b.iter()) == (a[0] >= b[0])); - - assert!(lt(c.iter(), b.iter()) == (c[0] < b[0])); - assert!(le(c.iter(), b.iter()) == (c[0] <= b[0])); - assert!(gt(c.iter(), b.iter()) == (c[0] > b[0])); - assert!(ge(c.iter(), b.iter()) == (c[0] >= b[0])); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use prelude::*; - - use cmp; - use owned::Box; - use uint; - use num; - - #[test] - fn test_counter_from_iter() { - let it = count(0, 5).take(10); - let xs: ~[int] = FromIterator::from_iter(it); - assert_eq!(xs, box [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); - } - - #[test] - fn test_iterator_chain() { - let xs = [0u, 1, 2, 3, 4, 5]; - let ys = [30u, 40, 50, 60]; - let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; - let mut it = xs.iter().chain(ys.iter()); - let mut i = 0; - for &x in it { - assert_eq!(x, expected[i]); - i += 1; - } - assert_eq!(i, expected.len()); - - let ys = count(30u, 10).take(4); - let mut it = xs.iter().map(|&x| x).chain(ys); - let mut i = 0; - for x in it { - assert_eq!(x, expected[i]); - i += 1; - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_filter_map() { - let mut it = count(0u, 1u).take(10) - .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None }); - assert_eq!(it.collect::<~[uint]>(), box [0*0, 2*2, 4*4, 6*6, 8*8]); - } - - #[test] - fn test_iterator_enumerate() { - let xs = [0u, 1, 2, 3, 4, 5]; - let mut it = xs.iter().enumerate(); - for (i, &x) in it { - assert_eq!(i, x); - } - } - - #[test] - fn test_iterator_peekable() { - let xs = box [0u, 1, 2, 3, 4, 5]; - let mut it = xs.iter().map(|&x|x).peekable(); - assert_eq!(it.peek().unwrap(), &0); - assert_eq!(it.next().unwrap(), 0); - assert_eq!(it.next().unwrap(), 1); - assert_eq!(it.next().unwrap(), 2); - assert_eq!(it.peek().unwrap(), &3); - assert_eq!(it.peek().unwrap(), &3); - assert_eq!(it.next().unwrap(), 3); - assert_eq!(it.next().unwrap(), 4); - assert_eq!(it.peek().unwrap(), &5); - assert_eq!(it.next().unwrap(), 5); - assert!(it.peek().is_none()); - assert!(it.next().is_none()); - } - - #[test] - fn test_iterator_take_while() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [0u, 1, 2, 3, 5, 13]; - let mut it = xs.iter().take_while(|&x| *x < 15u); - let mut i = 0; - for &x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_skip_while() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [15, 16, 17, 19]; - let mut it = xs.iter().skip_while(|&x| *x < 15u); - let mut i = 0; - for &x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_skip() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; - let ys = [13, 15, 16, 17, 19, 20, 30]; - let mut it = xs.iter().skip(5); - let mut i = 0; - for &x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_take() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [0u, 1, 2, 3, 5]; - let mut it = xs.iter().take(5); - let mut i = 0; - for &x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_scan() { - // test the type inference - fn add(old: &mut int, new: &uint) -> Option { - *old += *new as int; - Some(*old as f64) - } - let xs = [0u, 1, 2, 3, 4]; - let ys = [0f64, 1.0, 3.0, 6.0, 10.0]; - - let mut it = xs.iter().scan(0, add); - let mut i = 0; - for x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_flat_map() { - let xs = [0u, 3, 6]; - let ys = [0u, 1, 2, 3, 4, 5, 6, 7, 8]; - let mut it = xs.iter().flat_map(|&x| count(x, 1).take(3)); - let mut i = 0; - for x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_inspect() { - let xs = [1u, 2, 3, 4]; - let mut n = 0; - - let ys = xs.iter() - .map(|&x| x) - .inspect(|_| n += 1) - .collect::<~[uint]>(); - - assert_eq!(n, xs.len()); - assert_eq!(xs.as_slice(), ys.as_slice()); - } - - #[test] - fn test_unfoldr() { - fn count(st: &mut uint) -> Option { - if *st < 10 { - let ret = Some(*st); - *st += 1; - ret - } else { - None - } - } - - let mut it = Unfold::new(0, count); - let mut i = 0; - for counted in it { - assert_eq!(counted, i); - i += 1; - } - assert_eq!(i, 10); - } - - #[test] - fn test_cycle() { - let cycle_len = 3; - let it = count(0u, 1).take(cycle_len).cycle(); - assert_eq!(it.size_hint(), (uint::MAX, None)); - for (i, x) in it.take(100).enumerate() { - assert_eq!(i % cycle_len, x); - } - - let mut it = count(0u, 1).take(0).cycle(); - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_iterator_nth() { - let v = &[0, 1, 2, 3, 4]; - for i in range(0u, v.len()) { - assert_eq!(v.iter().nth(i).unwrap(), &v[i]); - } - } - - #[test] - fn test_iterator_last() { - let v = &[0, 1, 2, 3, 4]; - assert_eq!(v.iter().last().unwrap(), &4); - assert_eq!(v.slice(0, 1).iter().last().unwrap(), &0); - } - - #[test] - fn test_iterator_len() { - let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v.slice(0, 4).iter().len(), 4); - assert_eq!(v.slice(0, 10).iter().len(), 10); - assert_eq!(v.slice(0, 0).iter().len(), 0); - } - - #[test] - fn test_iterator_sum() { - let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v.slice(0, 4).iter().map(|&x| x).sum(), 6); - assert_eq!(v.iter().map(|&x| x).sum(), 55); - assert_eq!(v.slice(0, 0).iter().map(|&x| x).sum(), 0); - } - - #[test] - fn test_iterator_product() { - let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v.slice(0, 4).iter().map(|&x| x).product(), 0); - assert_eq!(v.slice(1, 5).iter().map(|&x| x).product(), 24); - assert_eq!(v.slice(0, 0).iter().map(|&x| x).product(), 1); - } - - #[test] - fn test_iterator_max() { - let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v.slice(0, 4).iter().map(|&x| x).max(), Some(3)); - assert_eq!(v.iter().map(|&x| x).max(), Some(10)); - assert_eq!(v.slice(0, 0).iter().map(|&x| x).max(), None); - } - - #[test] - fn test_iterator_min() { - let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v.slice(0, 4).iter().map(|&x| x).min(), Some(0)); - assert_eq!(v.iter().map(|&x| x).min(), Some(0)); - assert_eq!(v.slice(0, 0).iter().map(|&x| x).min(), None); - } - - #[test] - fn test_iterator_size_hint() { - let c = count(0, 1); - let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - let v2 = &[10, 11, 12]; - let vi = v.iter(); - - assert_eq!(c.size_hint(), (uint::MAX, None)); - assert_eq!(vi.size_hint(), (10, Some(10))); - - assert_eq!(c.take(5).size_hint(), (5, Some(5))); - assert_eq!(c.skip(5).size_hint().val1(), None); - assert_eq!(c.take_while(|_| false).size_hint(), (0, None)); - assert_eq!(c.skip_while(|_| false).size_hint(), (0, None)); - assert_eq!(c.enumerate().size_hint(), (uint::MAX, None)); - assert_eq!(c.chain(vi.map(|&i| i)).size_hint(), (uint::MAX, None)); - assert_eq!(c.zip(vi).size_hint(), (10, Some(10))); - assert_eq!(c.scan(0, |_,_| Some(0)).size_hint(), (0, None)); - assert_eq!(c.filter(|_| false).size_hint(), (0, None)); - assert_eq!(c.map(|_| 0).size_hint(), (uint::MAX, None)); - assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None)); - - assert_eq!(vi.take(5).size_hint(), (5, Some(5))); - assert_eq!(vi.take(12).size_hint(), (10, Some(10))); - assert_eq!(vi.skip(3).size_hint(), (7, Some(7))); - assert_eq!(vi.skip(12).size_hint(), (0, Some(0))); - assert_eq!(vi.take_while(|_| false).size_hint(), (0, Some(10))); - assert_eq!(vi.skip_while(|_| false).size_hint(), (0, Some(10))); - assert_eq!(vi.enumerate().size_hint(), (10, Some(10))); - assert_eq!(vi.chain(v2.iter()).size_hint(), (13, Some(13))); - assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3))); - assert_eq!(vi.scan(0, |_,_| Some(0)).size_hint(), (0, Some(10))); - assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10))); - assert_eq!(vi.map(|i| i+1).size_hint(), (10, Some(10))); - assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10))); - } - - #[test] - fn test_collect() { - let a = box [1, 2, 3, 4, 5]; - let b: ~[int] = a.iter().map(|&x| x).collect(); - assert_eq!(a, b); - } - - #[test] - fn test_all() { - let v: Box<&[int]> = box &[1, 2, 3, 4, 5]; - assert!(v.iter().all(|&x| x < 10)); - assert!(!v.iter().all(|&x| x % 2 == 0)); - assert!(!v.iter().all(|&x| x > 100)); - assert!(v.slice(0, 0).iter().all(|_| fail!())); - } - - #[test] - fn test_any() { - let v: Box<&[int]> = box &[1, 2, 3, 4, 5]; - assert!(v.iter().any(|&x| x < 10)); - assert!(v.iter().any(|&x| x % 2 == 0)); - assert!(!v.iter().any(|&x| x > 100)); - assert!(!v.slice(0, 0).iter().any(|_| fail!())); - } - - #[test] - fn test_find() { - let v: &[int] = &[1, 3, 9, 27, 103, 14, 11]; - assert_eq!(*v.iter().find(|x| *x & 1 == 0).unwrap(), 14); - assert_eq!(*v.iter().find(|x| *x % 3 == 0).unwrap(), 3); - assert!(v.iter().find(|x| *x % 12 == 0).is_none()); - } - - #[test] - fn test_position() { - let v = &[1, 3, 9, 27, 103, 14, 11]; - assert_eq!(v.iter().position(|x| *x & 1 == 0).unwrap(), 5); - assert_eq!(v.iter().position(|x| *x % 3 == 0).unwrap(), 1); - assert!(v.iter().position(|x| *x % 12 == 0).is_none()); - } - - #[test] - fn test_count() { - let xs = &[1, 2, 2, 1, 5, 9, 0, 2]; - assert_eq!(xs.iter().count(|x| *x == 2), 3); - assert_eq!(xs.iter().count(|x| *x == 5), 1); - assert_eq!(xs.iter().count(|x| *x == 95), 0); - } - - #[test] - fn test_max_by() { - let xs: &[int] = &[-3, 0, 1, 5, -10]; - assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10); - } - - #[test] - fn test_min_by() { - let xs: &[int] = &[-3, 0, 1, 5, -10]; - assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0); - } - - #[test] - fn test_by_ref() { - let mut xs = range(0, 10); - // sum the first five values - let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b); - assert_eq!(partial_sum, 10); - assert_eq!(xs.next(), Some(5)); - } - - #[test] - fn test_rev() { - let xs = [2, 4, 6, 8, 10, 12, 14, 16]; - let mut it = xs.iter(); - it.next(); - it.next(); - assert_eq!(it.rev().map(|&x| x).collect::<~[int]>(), box [16, 14, 12, 10, 8, 6]); - } - - #[test] - fn test_double_ended_map() { - let xs = [1, 2, 3, 4, 5, 6]; - let mut it = xs.iter().map(|&x| x * -1); - assert_eq!(it.next(), Some(-1)); - assert_eq!(it.next(), Some(-2)); - assert_eq!(it.next_back(), Some(-6)); - assert_eq!(it.next_back(), Some(-5)); - assert_eq!(it.next(), Some(-3)); - assert_eq!(it.next_back(), Some(-4)); - assert_eq!(it.next(), None); - } - - #[test] - fn test_double_ended_enumerate() { - let xs = [1, 2, 3, 4, 5, 6]; - let mut it = xs.iter().map(|&x| x).enumerate(); - assert_eq!(it.next(), Some((0, 1))); - assert_eq!(it.next(), Some((1, 2))); - assert_eq!(it.next_back(), Some((5, 6))); - assert_eq!(it.next_back(), Some((4, 5))); - assert_eq!(it.next_back(), Some((3, 4))); - assert_eq!(it.next_back(), Some((2, 3))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_double_ended_zip() { - let xs = [1, 2, 3, 4, 5, 6]; - let ys = [1, 2, 3, 7]; - let a = xs.iter().map(|&x| x); - let b = ys.iter().map(|&x| x); - let mut it = a.zip(b); - assert_eq!(it.next(), Some((1, 1))); - assert_eq!(it.next(), Some((2, 2))); - assert_eq!(it.next_back(), Some((4, 7))); - assert_eq!(it.next_back(), Some((3, 3))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_double_ended_filter() { - let xs = [1, 2, 3, 4, 5, 6]; - let mut it = xs.iter().filter(|&x| *x & 1 == 0); - assert_eq!(it.next_back().unwrap(), &6); - assert_eq!(it.next_back().unwrap(), &4); - assert_eq!(it.next().unwrap(), &2); - assert_eq!(it.next_back(), None); - } - - #[test] - fn test_double_ended_filter_map() { - let xs = [1, 2, 3, 4, 5, 6]; - let mut it = xs.iter().filter_map(|&x| if x & 1 == 0 { Some(x * 2) } else { None }); - assert_eq!(it.next_back().unwrap(), 12); - assert_eq!(it.next_back().unwrap(), 8); - assert_eq!(it.next().unwrap(), 4); - assert_eq!(it.next_back(), None); - } - - #[test] - fn test_double_ended_chain() { - let xs = [1, 2, 3, 4, 5]; - let ys = box [7, 9, 11]; - let mut it = xs.iter().chain(ys.iter()).rev(); - assert_eq!(it.next().unwrap(), &11) - assert_eq!(it.next().unwrap(), &9) - assert_eq!(it.next_back().unwrap(), &1) - assert_eq!(it.next_back().unwrap(), &2) - assert_eq!(it.next_back().unwrap(), &3) - assert_eq!(it.next_back().unwrap(), &4) - assert_eq!(it.next_back().unwrap(), &5) - assert_eq!(it.next_back().unwrap(), &7) - assert_eq!(it.next_back(), None) - } - - #[test] - fn test_rposition() { - fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } - fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' } - let v = box [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - - assert_eq!(v.iter().rposition(f), Some(3u)); - assert!(v.iter().rposition(g).is_none()); - } - - #[test] - #[should_fail] - fn test_rposition_fail() { - let v = [(box 0, @0), (box 0, @0), (box 0, @0), (box 0, @0)]; - let mut i = 0; - v.iter().rposition(|_elt| { - if i == 2 { - fail!() - } - i += 1; - false - }); - } - - - #[cfg(test)] - fn check_randacc_iter>(a: T, len: uint) - { - let mut b = a.clone(); - assert_eq!(len, b.indexable()); - let mut n = 0; - for (i, elt) in a.enumerate() { - assert!(Some(elt) == b.idx(i)); - n += 1; - } - assert_eq!(n, len); - assert!(None == b.idx(n)); - // call recursively to check after picking off an element - if len > 0 { - b.next(); - check_randacc_iter(b, len-1); - } - } - - - #[test] - fn test_double_ended_flat_map() { - let u = [0u,1]; - let v = [5,6,7,8]; - let mut it = u.iter().flat_map(|x| v.slice(*x, v.len()).iter()); - assert_eq!(it.next_back().unwrap(), &8); - assert_eq!(it.next().unwrap(), &5); - assert_eq!(it.next_back().unwrap(), &7); - assert_eq!(it.next_back().unwrap(), &6); - assert_eq!(it.next_back().unwrap(), &8); - assert_eq!(it.next().unwrap(), &6); - assert_eq!(it.next_back().unwrap(), &7); - assert_eq!(it.next_back(), None); - assert_eq!(it.next(), None); - assert_eq!(it.next_back(), None); - } - - #[test] - fn test_random_access_chain() { - let xs = [1, 2, 3, 4, 5]; - let ys = box [7, 9, 11]; - let mut it = xs.iter().chain(ys.iter()); - assert_eq!(it.idx(0).unwrap(), &1); - assert_eq!(it.idx(5).unwrap(), &7); - assert_eq!(it.idx(7).unwrap(), &11); - assert!(it.idx(8).is_none()); - - it.next(); - it.next(); - it.next_back(); - - assert_eq!(it.idx(0).unwrap(), &3); - assert_eq!(it.idx(4).unwrap(), &9); - assert!(it.idx(6).is_none()); - - check_randacc_iter(it, xs.len() + ys.len() - 3); - } - - #[test] - fn test_random_access_enumerate() { - let xs = [1, 2, 3, 4, 5]; - check_randacc_iter(xs.iter().enumerate(), xs.len()); - } - - #[test] - fn test_random_access_rev() { - let xs = [1, 2, 3, 4, 5]; - check_randacc_iter(xs.iter().rev(), xs.len()); - let mut it = xs.iter().rev(); - it.next(); - it.next_back(); - it.next(); - check_randacc_iter(it, xs.len() - 3); - } - - #[test] - fn test_random_access_zip() { - let xs = [1, 2, 3, 4, 5]; - let ys = [7, 9, 11]; - check_randacc_iter(xs.iter().zip(ys.iter()), cmp::min(xs.len(), ys.len())); - } - - #[test] - fn test_random_access_take() { - let xs = [1, 2, 3, 4, 5]; - let empty: &[int] = []; - check_randacc_iter(xs.iter().take(3), 3); - check_randacc_iter(xs.iter().take(20), xs.len()); - check_randacc_iter(xs.iter().take(0), 0); - check_randacc_iter(empty.iter().take(2), 0); - } - - #[test] - fn test_random_access_skip() { - let xs = [1, 2, 3, 4, 5]; - let empty: &[int] = []; - check_randacc_iter(xs.iter().skip(2), xs.len() - 2); - check_randacc_iter(empty.iter().skip(2), 0); - } - - #[test] - fn test_random_access_inspect() { - let xs = [1, 2, 3, 4, 5]; - - // test .map and .inspect that don't implement Clone - let mut it = xs.iter().inspect(|_| {}); - assert_eq!(xs.len(), it.indexable()); - for (i, elt) in xs.iter().enumerate() { - assert_eq!(Some(elt), it.idx(i)); - } - - } - - #[test] - fn test_random_access_map() { - let xs = [1, 2, 3, 4, 5]; - - let mut it = xs.iter().map(|x| *x); - assert_eq!(xs.len(), it.indexable()); - for (i, elt) in xs.iter().enumerate() { - assert_eq!(Some(*elt), it.idx(i)); - } - } - - #[test] - fn test_random_access_cycle() { - let xs = [1, 2, 3, 4, 5]; - let empty: &[int] = []; - check_randacc_iter(xs.iter().cycle().take(27), 27); - check_randacc_iter(empty.iter().cycle(), 0); - } - - #[test] - fn test_double_ended_range() { - assert_eq!(range(11i, 14).rev().collect::<~[int]>(), box [13i, 12, 11]); - for _ in range(10i, 0).rev() { - fail!("unreachable"); - } - - assert_eq!(range(11u, 14).rev().collect::<~[uint]>(), box [13u, 12, 11]); - for _ in range(10u, 0).rev() { - fail!("unreachable"); - } - } - - #[test] - fn test_range() { - /// A mock type to check Range when ToPrimitive returns None - struct Foo; - - impl ToPrimitive for Foo { - fn to_i64(&self) -> Option { None } - fn to_u64(&self) -> Option { None } - } - - impl Add for Foo { - fn add(&self, _: &Foo) -> Foo { - Foo - } - } - - impl Eq for Foo { - fn eq(&self, _: &Foo) -> bool { - true - } - } - - impl Ord for Foo { - fn lt(&self, _: &Foo) -> bool { - false - } - } - - impl Clone for Foo { - fn clone(&self) -> Foo { - Foo - } - } - - impl Mul for Foo { - fn mul(&self, _: &Foo) -> Foo { - Foo - } - } - - impl num::One for Foo { - fn one() -> Foo { - Foo - } - } - - assert_eq!(range(0i, 5).collect::<~[int]>(), box [0i, 1, 2, 3, 4]); - assert_eq!(range(-10i, -1).collect::<~[int]>(), box [-10, -9, -8, -7, -6, -5, -4, -3, -2]); - assert_eq!(range(0i, 5).rev().collect::<~[int]>(), box [4, 3, 2, 1, 0]); - assert_eq!(range(200, -5).collect::<~[int]>(), box []); - assert_eq!(range(200, -5).rev().collect::<~[int]>(), box []); - assert_eq!(range(200, 200).collect::<~[int]>(), box []); - assert_eq!(range(200, 200).rev().collect::<~[int]>(), box []); - - assert_eq!(range(0i, 100).size_hint(), (100, Some(100))); - // this test is only meaningful when sizeof uint < sizeof u64 - assert_eq!(range(uint::MAX - 1, uint::MAX).size_hint(), (1, Some(1))); - assert_eq!(range(-10i, -1).size_hint(), (9, Some(9))); - assert_eq!(range(Foo, Foo).size_hint(), (0, None)); - } - - #[test] - fn test_range_inclusive() { - assert_eq!(range_inclusive(0i, 5).collect::<~[int]>(), box [0i, 1, 2, 3, 4, 5]); - assert_eq!(range_inclusive(0i, 5).rev().collect::<~[int]>(), box [5i, 4, 3, 2, 1, 0]); - assert_eq!(range_inclusive(200, -5).collect::<~[int]>(), box []); - assert_eq!(range_inclusive(200, -5).rev().collect::<~[int]>(), box []); - assert_eq!(range_inclusive(200, 200).collect::<~[int]>(), box [200]); - assert_eq!(range_inclusive(200, 200).rev().collect::<~[int]>(), box [200]); - } - - #[test] - fn test_range_step() { - assert_eq!(range_step(0i, 20, 5).collect::<~[int]>(), box [0, 5, 10, 15]); - assert_eq!(range_step(20i, 0, -5).collect::<~[int]>(), box [20, 15, 10, 5]); - assert_eq!(range_step(20i, 0, -6).collect::<~[int]>(), box [20, 14, 8, 2]); - assert_eq!(range_step(200u8, 255, 50).collect::<~[u8]>(), box [200u8, 250]); - assert_eq!(range_step(200, -5, 1).collect::<~[int]>(), box []); - assert_eq!(range_step(200, 200, 1).collect::<~[int]>(), box []); - } - - #[test] - fn test_range_step_inclusive() { - assert_eq!(range_step_inclusive(0i, 20, 5).collect::<~[int]>(), box [0, 5, 10, 15, 20]); - assert_eq!(range_step_inclusive(20i, 0, -5).collect::<~[int]>(), box [20, 15, 10, 5, 0]); - assert_eq!(range_step_inclusive(20i, 0, -6).collect::<~[int]>(), box [20, 14, 8, 2]); - assert_eq!(range_step_inclusive(200u8, 255, 50).collect::<~[u8]>(), box [200u8, 250]); - assert_eq!(range_step_inclusive(200, -5, 1).collect::<~[int]>(), box []); - assert_eq!(range_step_inclusive(200, 200, 1).collect::<~[int]>(), box [200]); - } - - #[test] - fn test_reverse() { - let mut ys = [1, 2, 3, 4, 5]; - ys.mut_iter().reverse_(); - assert!(ys == [5, 4, 3, 2, 1]); - } - - #[test] - fn test_peekable_is_empty() { - let a = [1]; - let mut it = a.iter().peekable(); - assert!( !it.is_empty() ); - it.next(); - assert!( it.is_empty() ); - } - - #[test] - fn test_min_max() { - let v: [int, ..0] = []; - assert_eq!(v.iter().min_max(), NoElements); - - let v = [1i]; - assert!(v.iter().min_max() == OneElement(&1)); - - let v = [1i, 2, 3, 4, 5]; - assert!(v.iter().min_max() == MinMax(&1, &5)); - - let v = [1i, 2, 3, 4, 5, 6]; - assert!(v.iter().min_max() == MinMax(&1, &6)); - - let v = [1i, 1, 1, 1]; - assert!(v.iter().min_max() == MinMax(&1, &1)); - } - - #[test] - fn test_MinMaxResult() { - let r: MinMaxResult = NoElements; - assert_eq!(r.into_option(), None) - - let r = OneElement(1); - assert_eq!(r.into_option(), Some((1,1))); - - let r = MinMax(1,2); - assert_eq!(r.into_option(), Some((1,2))); - } -} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 64eff2c4762..63d86e43427 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -145,6 +145,7 @@ pub use core::clone; pub use core::container; pub use core::default; pub use core::intrinsics; +pub use core::iter; pub use core::mem; pub use core::option; pub use core::ptr; @@ -217,7 +218,6 @@ pub mod gc; pub mod from_str; pub mod num; -pub mod iter; pub mod to_str; pub mod hash; -- cgit 1.4.1-3-g733a5 From 5592a8f5db52a11b63547b661b3a635655b16980 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 21:55:14 -0700 Subject: core: Inherit the cmp module This removes the TotalOrd and TotalEq implementation macros, they will be added later to the numeric modules (where the other comparison implementations live). --- src/libcore/cmp.rs | 244 +++++++++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 1 + src/libstd/cmp.rs | 296 -------------------------------------------------- src/libstd/fmt/mod.rs | 11 ++ src/libstd/lib.rs | 4 +- 5 files changed, 257 insertions(+), 299 deletions(-) create mode 100644 src/libcore/cmp.rs delete mode 100644 src/libstd/cmp.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs new file mode 100644 index 00000000000..867871805d0 --- /dev/null +++ b/src/libcore/cmp.rs @@ -0,0 +1,244 @@ +// Copyright 2012-2013 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. + +//! Defines the `Ord` and `Eq` comparison traits. +//! +//! This module defines both `Ord` and `Eq` traits which are used by the +//! compiler to implement comparison operators. Rust programs may implement +//!`Ord` to overload the `<`, `<=`, `>`, and `>=` operators, and may implement +//! `Eq` to overload the `==` and `!=` operators. +//! +//! For example, to define a type with a customized definition for the Eq +//! operators, you could do the following: +//! +//! ```rust +//! // Our type. +//! struct SketchyNum { +//! num : int +//! } +//! +//! // Our implementation of `Eq` to support `==` and `!=`. +//! impl Eq for SketchyNum { +//! // Our custom eq allows numbers which are near each other to be equal! :D +//! fn eq(&self, other: &SketchyNum) -> bool { +//! (self.num - other.num).abs() < 5 +//! } +//! } +//! +//! // Now these binary operators will work when applied! +//! assert!(SketchyNum {num: 37} == SketchyNum {num: 34}); +//! assert!(SketchyNum {num: 25} != SketchyNum {num: 57}); +//! ``` + +/// Trait for values that can be compared for equality and inequality. +/// +/// This trait allows partial equality, where types can be unordered instead of +/// strictly equal or unequal. For example, with the built-in floating-point +/// types `a == b` and `a != b` will both evaluate to false if either `a` or +/// `b` is NaN (cf. IEEE 754-2008 section 5.11). +/// +/// Eq only requires the `eq` method to be implemented; `ne` is its negation by +/// default. +/// +/// Eventually, this will be implemented by default for types that implement +/// `TotalEq`. +#[lang="eq"] +pub trait Eq { + /// This method tests for `self` and `other` values to be equal, and is used by `==`. + fn eq(&self, other: &Self) -> bool; + + /// This method tests for `!=`. + #[inline] + fn ne(&self, other: &Self) -> bool { !self.eq(other) } +} + +/// Trait for equality comparisons which are [equivalence relations]( +/// https://en.wikipedia.org/wiki/Equivalence_relation). +/// +/// This means, that in addition to `a == b` and `a != b` being strict +/// inverses, the equality must be (for all `a`, `b` and `c`): +/// +/// - reflexive: `a == a`; +/// - symmetric: `a == b` implies `b == a`; and +/// - transitive: `a == b` and `b == c` implies `a == c`. +pub trait TotalEq: Eq { + // FIXME #13101: this method is used solely by #[deriving] to + // assert that every component of a type implements #[deriving] + // itself, the current deriving infrastructure means doing this + // assertion without using a method on this trait is nearly + // impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[inline(always)] + fn assert_receiver_is_total_eq(&self) {} +} + +/// An ordering is, e.g, a result of a comparison between two values. +#[deriving(Clone, Eq)] +pub enum Ordering { + /// An ordering where a compared value is less [than another]. + Less = -1, + /// An ordering where a compared value is equal [to another]. + Equal = 0, + /// An ordering where a compared value is greater [than another]. + Greater = 1 +} + +/// Trait for types that form a [total order]( +/// https://en.wikipedia.org/wiki/Total_order). +/// +/// An order is a total order if it is (for all `a`, `b` and `c`): +/// +/// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is +/// true; and +/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for +/// both `==` and `>`. +pub trait TotalOrd: TotalEq + Ord { + /// This method returns an ordering between `self` and `other` values. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching + /// the expression `self other` if true. For example: + /// + /// ``` + /// assert_eq!( 5u.cmp(&10), Less); // because 5 < 10 + /// assert_eq!(10u.cmp(&5), Greater); // because 10 > 5 + /// assert_eq!( 5u.cmp(&5), Equal); // because 5 == 5 + /// ``` + fn cmp(&self, other: &Self) -> Ordering; +} + +impl TotalEq for Ordering {} + +impl TotalOrd for Ordering { + #[inline] + fn cmp(&self, other: &Ordering) -> Ordering { + (*self as int).cmp(&(*other as int)) + } +} + +impl Ord for Ordering { + #[inline] + fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) } +} + +/// Combine orderings, lexically. +/// +/// For example for a type `(int, int)`, two comparisons could be done. +/// If the first ordering is different, the first ordering is all that must be returned. +/// If the first ordering is equal, then second ordering is returned. +#[inline] +pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering { + match o1 { + Equal => o2, + _ => o1 + } +} + +/// Trait for values that can be compared for a sort-order. +/// +/// Ord only requires implementation of the `lt` method, +/// with the others generated from default implementations. +/// +/// However it remains possible to implement the others separately, +/// for compatibility with floating-point NaN semantics +/// (cf. IEEE 754-2008 section 5.11). +#[lang="ord"] +pub trait Ord: Eq { + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. + fn lt(&self, other: &Self) -> bool; + + /// This method tests less than or equal to (`<=`). + #[inline] + fn le(&self, other: &Self) -> bool { !other.lt(self) } + + /// This method tests greater than (`>`). + #[inline] + fn gt(&self, other: &Self) -> bool { other.lt(self) } + + /// This method tests greater than or equal to (`>=`). + #[inline] + fn ge(&self, other: &Self) -> bool { !self.lt(other) } +} + +/// The equivalence relation. Two values may be equivalent even if they are +/// of different types. The most common use case for this relation is +/// container types; e.g. it is often desirable to be able to use `&str` +/// values to look up entries in a container with `~str` keys. +pub trait Equiv { + /// Implement this function to decide equivalent values. + fn equiv(&self, other: &T) -> bool; +} + +/// Compare and return the minimum of two values. +#[inline] +pub fn min(v1: T, v2: T) -> T { + if v1 < v2 { v1 } else { v2 } +} + +/// Compare and return the maximum of two values. +#[inline] +pub fn max(v1: T, v2: T) -> T { + if v1 > v2 { v1 } else { v2 } +} + +#[cfg(test)] +mod test { + use super::lexical_ordering; + + #[test] + fn test_int_totalord() { + assert_eq!(5u.cmp(&10), Less); + assert_eq!(10u.cmp(&5), Greater); + assert_eq!(5u.cmp(&5), Equal); + assert_eq!((-5u).cmp(&12), Less); + assert_eq!(12u.cmp(-5), Greater); + } + + #[test] + fn test_ordering_order() { + assert!(Less < Equal); + assert_eq!(Greater.cmp(&Less), Greater); + } + + #[test] + fn test_lexical_ordering() { + fn t(o1: Ordering, o2: Ordering, e: Ordering) { + assert_eq!(lexical_ordering(o1, o2), e); + } + + let xs = [Less, Equal, Greater]; + for &o in xs.iter() { + t(Less, o, Less); + t(Equal, o, o); + t(Greater, o, Greater); + } + } + + #[test] + fn test_user_defined_eq() { + // Our type. + struct SketchyNum { + num : int + } + + // Our implementation of `Eq` to support `==` and `!=`. + impl Eq for SketchyNum { + // Our custom eq allows numbers which are near each other to be equal! :D + fn eq(&self, other: &SketchyNum) -> bool { + (self.num - other.num).abs() < 5 + } + } + + // Now these binary operators will work when applied! + assert!(SketchyNum {num: 37} == SketchyNum {num: 34}); + assert!(SketchyNum {num: 25} != SketchyNum {num: 57}); + } +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index c4a5254b1eb..e5f8011f91e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -30,6 +30,7 @@ pub mod ptr; /* Core language traits */ +pub mod cmp; pub mod kinds; pub mod ops; pub mod ty; diff --git a/src/libstd/cmp.rs b/src/libstd/cmp.rs deleted file mode 100644 index a6d6649aca0..00000000000 --- a/src/libstd/cmp.rs +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright 2012-2013 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. - -//! Defines the `Ord` and `Eq` comparison traits. -//! -//! This module defines both `Ord` and `Eq` traits which are used by the -//! compiler to implement comparison operators. Rust programs may implement -//!`Ord` to overload the `<`, `<=`, `>`, and `>=` operators, and may implement -//! `Eq` to overload the `==` and `!=` operators. -//! -//! For example, to define a type with a customized definition for the Eq -//! operators, you could do the following: -//! -//! ```rust -//! // Our type. -//! struct SketchyNum { -//! num : int -//! } -//! -//! // Our implementation of `Eq` to support `==` and `!=`. -//! impl Eq for SketchyNum { -//! // Our custom eq allows numbers which are near each other to be equal! :D -//! fn eq(&self, other: &SketchyNum) -> bool { -//! (self.num - other.num).abs() < 5 -//! } -//! } -//! -//! // Now these binary operators will work when applied! -//! assert!(SketchyNum {num: 37} == SketchyNum {num: 34}); -//! assert!(SketchyNum {num: 25} != SketchyNum {num: 57}); -//! ``` - -/// Trait for values that can be compared for equality and inequality. -/// -/// This trait allows partial equality, where types can be unordered instead of -/// strictly equal or unequal. For example, with the built-in floating-point -/// types `a == b` and `a != b` will both evaluate to false if either `a` or -/// `b` is NaN (cf. IEEE 754-2008 section 5.11). -/// -/// Eq only requires the `eq` method to be implemented; `ne` is its negation by -/// default. -/// -/// Eventually, this will be implemented by default for types that implement -/// `TotalEq`. -#[lang="eq"] -pub trait Eq { - /// This method tests for `self` and `other` values to be equal, and is used by `==`. - fn eq(&self, other: &Self) -> bool; - - /// This method tests for `!=`. - #[inline] - fn ne(&self, other: &Self) -> bool { !self.eq(other) } -} - -/// Trait for equality comparisons which are [equivalence relations]( -/// https://en.wikipedia.org/wiki/Equivalence_relation). -/// -/// This means, that in addition to `a == b` and `a != b` being strict -/// inverses, the equality must be (for all `a`, `b` and `c`): -/// -/// - reflexive: `a == a`; -/// - symmetric: `a == b` implies `b == a`; and -/// - transitive: `a == b` and `b == c` implies `a == c`. -pub trait TotalEq: Eq { - // FIXME #13101: this method is used solely by #[deriving] to - // assert that every component of a type implements #[deriving] - // itself, the current deriving infrastructure means doing this - // assertion without using a method on this trait is nearly - // impossible. - // - // This should never be implemented by hand. - #[doc(hidden)] - #[inline(always)] - fn assert_receiver_is_total_eq(&self) {} -} - -/// A macro which defines an implementation of TotalEq for a given type. -macro_rules! totaleq_impl( - ($t:ty) => { - impl TotalEq for $t {} - } -) - -totaleq_impl!(bool) - -totaleq_impl!(u8) -totaleq_impl!(u16) -totaleq_impl!(u32) -totaleq_impl!(u64) - -totaleq_impl!(i8) -totaleq_impl!(i16) -totaleq_impl!(i32) -totaleq_impl!(i64) - -totaleq_impl!(int) -totaleq_impl!(uint) - -totaleq_impl!(char) - -/// An ordering is, e.g, a result of a comparison between two values. -#[deriving(Clone, Eq, Show)] -pub enum Ordering { - /// An ordering where a compared value is less [than another]. - Less = -1, - /// An ordering where a compared value is equal [to another]. - Equal = 0, - /// An ordering where a compared value is greater [than another]. - Greater = 1 -} - -/// Trait for types that form a [total order]( -/// https://en.wikipedia.org/wiki/Total_order). -/// -/// An order is a total order if it is (for all `a`, `b` and `c`): -/// -/// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is -/// true; and -/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for -/// both `==` and `>`. -pub trait TotalOrd: TotalEq + Ord { - /// This method returns an ordering between `self` and `other` values. - /// - /// By convention, `self.cmp(&other)` returns the ordering matching - /// the expression `self other` if true. For example: - /// - /// ``` - /// assert_eq!( 5u.cmp(&10), Less); // because 5 < 10 - /// assert_eq!(10u.cmp(&5), Greater); // because 10 > 5 - /// assert_eq!( 5u.cmp(&5), Equal); // because 5 == 5 - /// ``` - fn cmp(&self, other: &Self) -> Ordering; -} - -impl TotalEq for Ordering {} -impl TotalOrd for Ordering { - #[inline] - fn cmp(&self, other: &Ordering) -> Ordering { - (*self as int).cmp(&(*other as int)) - } -} - -impl Ord for Ordering { - #[inline] - fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) } -} - -/// A macro which defines an implementation of TotalOrd for a given type. -macro_rules! totalord_impl( - ($t:ty) => { - impl TotalOrd for $t { - #[inline] - fn cmp(&self, other: &$t) -> Ordering { - if *self < *other { Less } - else if *self > *other { Greater } - else { Equal } - } - } - } -) - -totalord_impl!(u8) -totalord_impl!(u16) -totalord_impl!(u32) -totalord_impl!(u64) - -totalord_impl!(i8) -totalord_impl!(i16) -totalord_impl!(i32) -totalord_impl!(i64) - -totalord_impl!(int) -totalord_impl!(uint) - -totalord_impl!(char) - -/// Combine orderings, lexically. -/// -/// For example for a type `(int, int)`, two comparisons could be done. -/// If the first ordering is different, the first ordering is all that must be returned. -/// If the first ordering is equal, then second ordering is returned. -#[inline] -pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering { - match o1 { - Equal => o2, - _ => o1 - } -} - -/// Trait for values that can be compared for a sort-order. -/// -/// Ord only requires implementation of the `lt` method, -/// with the others generated from default implementations. -/// -/// However it remains possible to implement the others separately, -/// for compatibility with floating-point NaN semantics -/// (cf. IEEE 754-2008 section 5.11). -#[lang="ord"] -pub trait Ord: Eq { - /// This method tests less than (for `self` and `other`) and is used by the `<` operator. - fn lt(&self, other: &Self) -> bool; - - /// This method tests less than or equal to (`<=`). - #[inline] - fn le(&self, other: &Self) -> bool { !other.lt(self) } - - /// This method tests greater than (`>`). - #[inline] - fn gt(&self, other: &Self) -> bool { other.lt(self) } - - /// This method tests greater than or equal to (`>=`). - #[inline] - fn ge(&self, other: &Self) -> bool { !self.lt(other) } -} - -/// The equivalence relation. Two values may be equivalent even if they are -/// of different types. The most common use case for this relation is -/// container types; e.g. it is often desirable to be able to use `&str` -/// values to look up entries in a container with `~str` keys. -pub trait Equiv { - /// Implement this function to decide equivalent values. - fn equiv(&self, other: &T) -> bool; -} - -/// Compare and return the minimum of two values. -#[inline] -pub fn min(v1: T, v2: T) -> T { - if v1 < v2 { v1 } else { v2 } -} - -/// Compare and return the maximum of two values. -#[inline] -pub fn max(v1: T, v2: T) -> T { - if v1 > v2 { v1 } else { v2 } -} - -#[cfg(test)] -mod test { - use super::lexical_ordering; - - #[test] - fn test_int_totalord() { - assert_eq!(5u.cmp(&10), Less); - assert_eq!(10u.cmp(&5), Greater); - assert_eq!(5u.cmp(&5), Equal); - assert_eq!((-5u).cmp(&12), Less); - assert_eq!(12u.cmp(-5), Greater); - } - - #[test] - fn test_ordering_order() { - assert!(Less < Equal); - assert_eq!(Greater.cmp(&Less), Greater); - } - - #[test] - fn test_lexical_ordering() { - fn t(o1: Ordering, o2: Ordering, e: Ordering) { - assert_eq!(lexical_ordering(o1, o2), e); - } - - let xs = [Less, Equal, Greater]; - for &o in xs.iter() { - t(Less, o, Less); - t(Equal, o, o); - t(Greater, o, Greater); - } - } - - #[test] - fn test_user_defined_eq() { - // Our type. - struct SketchyNum { - num : int - } - - // Our implementation of `Eq` to support `==` and `!=`. - impl Eq for SketchyNum { - // Our custom eq allows numbers which are near each other to be equal! :D - fn eq(&self, other: &SketchyNum) -> bool { - (self.num - other.num).abs() < 5 - } - } - - // Now these binary operators will work when applied! - assert!(SketchyNum {num: 37} == SketchyNum {num: 34}); - assert!(SketchyNum {num: 25} != SketchyNum {num: 57}); - } -} diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index 067ce608980..4a81a6b38a7 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -486,6 +486,7 @@ will look like `"\\{"`. use any; use cast; use char::Char; +use cmp; use container::Container; use io::MemWriter; use io; @@ -1315,5 +1316,15 @@ impl Show for iter::MinMaxResult { } } +impl Show for cmp::Ordering { + fn fmt(&self, f: &mut Formatter) -> Result { + match *self { + cmp::Less => write!(f.buf, "Less"), + cmp::Greater => write!(f.buf, "Greater"), + cmp::Equal => write!(f.buf, "Equal"), + } + } +} + // If you expected tests to be here, look instead at the run-pass/ifmt.rs test, // it's a lot easier than creating all of the rt::Piece structures here. diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 63d86e43427..041959f2ee7 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -135,6 +135,7 @@ extern crate core; #[cfg(not(test))] pub use kinds = core::kinds; #[cfg(not(test))] pub use ops = core::ops; +#[cfg(not(test))] pub use cmp = core::cmp; #[cfg(not(test))] pub use ty = core::ty; pub use core::any; @@ -207,13 +208,10 @@ mod reference; pub mod rc; pub mod gc; - /* Core language traits */ -#[cfg(not(test))] pub mod cmp; #[cfg(not(test))] pub mod owned; - /* Common traits */ pub mod from_str; -- cgit 1.4.1-3-g733a5 From c5229e5d2ea6168ec80a7feeea1a513b2b3176c0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 30 Apr 2014 22:00:31 -0700 Subject: core: Inhert ~/@/& cmp traits, remove old modules This commit removes the std::{managed, reference} modules. The modules serve essentially no purpose, and the only free function removed was `managed::ptr_eq` which can be achieved by comparing references. [breaking-change] --- src/libcore/cmp.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/gc.rs | 3 +- src/libstd/lib.rs | 2 -- src/libstd/managed.rs | 58 -------------------------------------- src/libstd/owned.rs | 31 -------------------- src/libstd/reference.rs | 57 ------------------------------------- 6 files changed, 76 insertions(+), 150 deletions(-) delete mode 100644 src/libstd/managed.rs delete mode 100644 src/libstd/reference.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 867871805d0..0ad2a465522 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -189,6 +189,81 @@ pub fn max(v1: T, v2: T) -> T { if v1 > v2 { v1 } else { v2 } } +// Implementation of Eq/TotalEq for some primitive types +#[cfg(not(test))] +mod impls { + use cmp::{Ord, TotalOrd, Eq, TotalEq, Ordering}; + + // & pointers + impl<'a, T: Eq> Eq for &'a T { + #[inline] + fn eq(&self, other: & &'a T) -> bool { *(*self) == *(*other) } + #[inline] + fn ne(&self, other: & &'a T) -> bool { *(*self) != *(*other) } + } + impl<'a, T: Ord> Ord for &'a T { + #[inline] + fn lt(&self, other: & &'a T) -> bool { *(*self) < *(*other) } + #[inline] + fn le(&self, other: & &'a T) -> bool { *(*self) <= *(*other) } + #[inline] + fn ge(&self, other: & &'a T) -> bool { *(*self) >= *(*other) } + #[inline] + fn gt(&self, other: & &'a T) -> bool { *(*self) > *(*other) } + } + impl<'a, T: TotalOrd> TotalOrd for &'a T { + #[inline] + fn cmp(&self, other: & &'a T) -> Ordering { (**self).cmp(*other) } + } + impl<'a, T: TotalEq> TotalEq for &'a T {} + + // @ pointers + impl Eq for @T { + #[inline] + fn eq(&self, other: &@T) -> bool { *(*self) == *(*other) } + #[inline] + fn ne(&self, other: &@T) -> bool { *(*self) != *(*other) } + } + impl Ord for @T { + #[inline] + fn lt(&self, other: &@T) -> bool { *(*self) < *(*other) } + #[inline] + fn le(&self, other: &@T) -> bool { *(*self) <= *(*other) } + #[inline] + fn ge(&self, other: &@T) -> bool { *(*self) >= *(*other) } + #[inline] + fn gt(&self, other: &@T) -> bool { *(*self) > *(*other) } + } + impl TotalOrd for @T { + #[inline] + fn cmp(&self, other: &@T) -> Ordering { (**self).cmp(*other) } + } + impl TotalEq for @T {} + + // ~ pointers + impl Eq for ~T { + #[inline] + fn eq(&self, other: &~T) -> bool { *(*self) == *(*other) } + #[inline] + fn ne(&self, other: &~T) -> bool { *(*self) != *(*other) } + } + impl Ord for ~T { + #[inline] + fn lt(&self, other: &~T) -> bool { *(*self) < *(*other) } + #[inline] + fn le(&self, other: &~T) -> bool { *(*self) <= *(*other) } + #[inline] + fn ge(&self, other: &~T) -> bool { *(*self) >= *(*other) } + #[inline] + fn gt(&self, other: &~T) -> bool { *(*self) > *(*other) } + } + impl TotalOrd for ~T { + #[inline] + fn cmp(&self, other: &~T) -> Ordering { (**self).cmp(*other) } + } + impl TotalEq for ~T {} +} + #[cfg(test)] mod test { use super::lexical_ordering; diff --git a/src/libstd/gc.rs b/src/libstd/gc.rs index 7387eff3dfc..9260d8d7ab2 100644 --- a/src/libstd/gc.rs +++ b/src/libstd/gc.rs @@ -20,7 +20,6 @@ collector is task-local so `Gc` is not sendable. use kinds::marker; use clone::Clone; -use managed; /// Immutable garbage-collected pointer type #[lang="gc"] @@ -55,7 +54,7 @@ impl Gc { /// Determine if two garbage-collected boxes point to the same object #[inline] pub fn ptr_eq(&self, other: &Gc) -> bool { - managed::ptr_eq(self.ptr, other.ptr) + self.borrow() as *T == other.borrow() as *T } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 041959f2ee7..95d67eb77d1 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -203,8 +203,6 @@ pub mod strbuf; pub mod ascii; -mod managed; -mod reference; pub mod rc; pub mod gc; diff --git a/src/libstd/managed.rs b/src/libstd/managed.rs deleted file mode 100644 index bf73c05440c..00000000000 --- a/src/libstd/managed.rs +++ /dev/null @@ -1,58 +0,0 @@ -// 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. - -//! Operations on managed box types - -#[cfg(not(test))] use cmp::*; - -/// Determine if two shared boxes point to the same object -#[inline] -pub fn ptr_eq(a: @T, b: @T) -> bool { - &*a as *T == &*b as *T -} - -#[cfg(not(test))] -impl Eq for @T { - #[inline] - fn eq(&self, other: &@T) -> bool { *(*self) == *(*other) } - #[inline] - fn ne(&self, other: &@T) -> bool { *(*self) != *(*other) } -} - -#[cfg(not(test))] -impl Ord for @T { - #[inline] - fn lt(&self, other: &@T) -> bool { *(*self) < *(*other) } - #[inline] - fn le(&self, other: &@T) -> bool { *(*self) <= *(*other) } - #[inline] - fn ge(&self, other: &@T) -> bool { *(*self) >= *(*other) } - #[inline] - fn gt(&self, other: &@T) -> bool { *(*self) > *(*other) } -} - -#[cfg(not(test))] -impl TotalOrd for @T { - #[inline] - fn cmp(&self, other: &@T) -> Ordering { (**self).cmp(*other) } -} - -#[cfg(not(test))] -impl TotalEq for @T {} - -#[test] -fn test() { - let x = @3; - let y = @3; - assert!((ptr_eq::(x, x))); - assert!((ptr_eq::(y, y))); - assert!((!ptr_eq::(x, y))); - assert!((!ptr_eq::(y, x))); -} diff --git a/src/libstd/owned.rs b/src/libstd/owned.rs index 48b80e0ca8e..4f282c5c9e9 100644 --- a/src/libstd/owned.rs +++ b/src/libstd/owned.rs @@ -10,8 +10,6 @@ //! Operations on unique pointer types -#[cfg(not(test))] use cmp::*; - /// A value that represents the global exchange heap. This is the default /// place that the `box` keyword allocates into when no place is supplied. /// @@ -33,32 +31,3 @@ pub struct Box(*T); #[cfg(test)] pub struct Box(*T); - -#[cfg(not(test))] -impl Eq for Box { - #[inline] - fn eq(&self, other: &Box) -> bool { *(*self) == *(*other) } - #[inline] - fn ne(&self, other: &Box) -> bool { *(*self) != *(*other) } -} - -#[cfg(not(test))] -impl Ord for Box { - #[inline] - fn lt(&self, other: &Box) -> bool { *(*self) < *(*other) } - #[inline] - fn le(&self, other: &Box) -> bool { *(*self) <= *(*other) } - #[inline] - fn ge(&self, other: &Box) -> bool { *(*self) >= *(*other) } - #[inline] - fn gt(&self, other: &Box) -> bool { *(*self) > *(*other) } -} - -#[cfg(not(test))] -impl TotalOrd for Box { - #[inline] - fn cmp(&self, other: &Box) -> Ordering { (**self).cmp(*other) } -} - -#[cfg(not(test))] -impl TotalEq for Box {} diff --git a/src/libstd/reference.rs b/src/libstd/reference.rs deleted file mode 100644 index eb615afd85f..00000000000 --- a/src/libstd/reference.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2012-2013 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. - -//! Utilities for references - -#[cfg(not(test))] -use cmp::{Eq, Ord, Ordering, TotalEq, TotalOrd}; - -// Equality for region pointers -#[cfg(not(test))] -impl<'a, T: Eq> Eq for &'a T { - #[inline] - fn eq(&self, other: & &'a T) -> bool { - *(*self) == *(*other) - } - #[inline] - fn ne(&self, other: & &'a T) -> bool { - *(*self) != *(*other) - } -} - -// Comparison for region pointers -#[cfg(not(test))] -impl<'a, T: Ord> Ord for &'a T { - #[inline] - fn lt(&self, other: & &'a T) -> bool { - *(*self) < *(*other) - } - #[inline] - fn le(&self, other: & &'a T) -> bool { - *(*self) <= *(*other) - } - #[inline] - fn ge(&self, other: & &'a T) -> bool { - *(*self) >= *(*other) - } - #[inline] - fn gt(&self, other: & &'a T) -> bool { - *(*self) > *(*other) - } -} - -#[cfg(not(test))] -impl<'a, T: TotalOrd> TotalOrd for &'a T { - #[inline] - fn cmp(&self, other: & &'a T) -> Ordering { (**self).cmp(*other) } -} - -#[cfg(not(test))] -impl<'a, T: TotalEq> TotalEq for &'a T {} -- cgit 1.4.1-3-g733a5 From f62c121eb0de35ac03a7860e6039202f2522e527 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 1 May 2014 11:19:56 -0700 Subject: core: Inherit the cell module --- src/libcore/cell.rs | 310 ++++++++++++++++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 3 +- src/libstd/cell.rs | 317 -------------------------------------------------- src/libstd/fmt/mod.rs | 2 + src/libstd/lib.rs | 2 +- 5 files changed, 315 insertions(+), 319 deletions(-) create mode 100644 src/libcore/cell.rs delete mode 100644 src/libstd/cell.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs new file mode 100644 index 00000000000..8c520a4788a --- /dev/null +++ b/src/libcore/cell.rs @@ -0,0 +1,310 @@ +// Copyright 2012-2013 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. + +//! Types dealing with dynamic mutability + +use clone::Clone; +use cmp::Eq; +use kinds::{marker, Copy}; +use ops::{Deref, DerefMut, Drop}; +use option::{None, Option, Some}; +use ty::Unsafe; + +/// A mutable memory location that admits only `Copy` data. +pub struct Cell { + value: Unsafe, + noshare: marker::NoShare, +} + +impl Cell { + /// Creates a new `Cell` containing the given value. + pub fn new(value: T) -> Cell { + Cell { + value: Unsafe::new(value), + noshare: marker::NoShare, + } + } + + /// Returns a copy of the contained value. + #[inline] + pub fn get(&self) -> T { + unsafe{ *self.value.get() } + } + + /// Sets the contained value. + #[inline] + pub fn set(&self, value: T) { + unsafe { + *self.value.get() = value; + } + } +} + +impl Clone for Cell { + fn clone(&self) -> Cell { + Cell::new(self.get()) + } +} + +impl Eq for Cell { + fn eq(&self, other: &Cell) -> bool { + self.get() == other.get() + } +} + +/// A mutable memory location with dynamically checked borrow rules +pub struct RefCell { + value: Unsafe, + borrow: Cell, + nocopy: marker::NoCopy, + noshare: marker::NoShare, +} + +// Values [1, MAX-1] represent the number of `Ref` active +// (will not outgrow its range since `uint` is the size of the address space) +type BorrowFlag = uint; +static UNUSED: BorrowFlag = 0; +static WRITING: BorrowFlag = -1; + +impl RefCell { + /// Create a new `RefCell` containing `value` + pub fn new(value: T) -> RefCell { + RefCell { + value: Unsafe::new(value), + borrow: Cell::new(UNUSED), + nocopy: marker::NoCopy, + noshare: marker::NoShare, + } + } + + /// Consumes the `RefCell`, returning the wrapped value. + pub fn unwrap(self) -> T { + debug_assert!(self.borrow.get() == UNUSED); + unsafe{self.value.unwrap()} + } + + /// Attempts to immutably borrow the wrapped value. + /// + /// The borrow lasts until the returned `Ref` exits scope. Multiple + /// immutable borrows can be taken out at the same time. + /// + /// Returns `None` if the value is currently mutably borrowed. + pub fn try_borrow<'a>(&'a self) -> Option> { + match self.borrow.get() { + WRITING => None, + borrow => { + self.borrow.set(borrow + 1); + Some(Ref { parent: self }) + } + } + } + + /// Immutably borrows the wrapped value. + /// + /// The borrow lasts until the returned `Ref` exits scope. Multiple + /// immutable borrows can be taken out at the same time. + /// + /// # Failure + /// + /// Fails if the value is currently mutably borrowed. + pub fn borrow<'a>(&'a self) -> Ref<'a, T> { + match self.try_borrow() { + Some(ptr) => ptr, + None => fail!("RefCell already mutably borrowed") + } + } + + /// Mutably borrows the wrapped value. + /// + /// The borrow lasts until the returned `RefMut` exits scope. The value + /// cannot be borrowed while this borrow is active. + /// + /// Returns `None` if the value is currently borrowed. + pub fn try_borrow_mut<'a>(&'a self) -> Option> { + match self.borrow.get() { + UNUSED => { + self.borrow.set(WRITING); + Some(RefMut { parent: self }) + }, + _ => None + } + } + + /// Mutably borrows the wrapped value. + /// + /// The borrow lasts until the returned `RefMut` exits scope. The value + /// cannot be borrowed while this borrow is active. + /// + /// # Failure + /// + /// Fails if the value is currently borrowed. + pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> { + match self.try_borrow_mut() { + Some(ptr) => ptr, + None => fail!("RefCell already borrowed") + } + } +} + +impl Clone for RefCell { + fn clone(&self) -> RefCell { + RefCell::new(self.borrow().clone()) + } +} + +impl Eq for RefCell { + fn eq(&self, other: &RefCell) -> bool { + *self.borrow() == *other.borrow() + } +} + +/// Wraps a borrowed reference to a value in a `RefCell` box. +pub struct Ref<'b, T> { + parent: &'b RefCell +} + +#[unsafe_destructor] +impl<'b, T> Drop for Ref<'b, T> { + fn drop(&mut self) { + let borrow = self.parent.borrow.get(); + debug_assert!(borrow != WRITING && borrow != UNUSED); + self.parent.borrow.set(borrow - 1); + } +} + +impl<'b, T> Deref for Ref<'b, T> { + #[inline] + fn deref<'a>(&'a self) -> &'a T { + unsafe { &*self.parent.value.get() } + } +} + +/// Wraps a mutable borrowed reference to a value in a `RefCell` box. +pub struct RefMut<'b, T> { + parent: &'b RefCell +} + +#[unsafe_destructor] +impl<'b, T> Drop for RefMut<'b, T> { + fn drop(&mut self) { + let borrow = self.parent.borrow.get(); + debug_assert!(borrow == WRITING); + self.parent.borrow.set(UNUSED); + } +} + +impl<'b, T> Deref for RefMut<'b, T> { + #[inline] + fn deref<'a>(&'a self) -> &'a T { + unsafe { &*self.parent.value.get() } + } +} + +impl<'b, T> DerefMut for RefMut<'b, T> { + #[inline] + fn deref_mut<'a>(&'a mut self) -> &'a mut T { + unsafe { &mut *self.parent.value.get() } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn smoketest_cell() { + let x = Cell::new(10); + assert_eq!(x, Cell::new(10)); + assert_eq!(x.get(), 10); + x.set(20); + assert_eq!(x, Cell::new(20)); + assert_eq!(x.get(), 20); + + let y = Cell::new((30, 40)); + assert_eq!(y, Cell::new((30, 40))); + assert_eq!(y.get(), (30, 40)); + } + + #[test] + fn cell_has_sensible_show() { + use str::StrSlice; + + let x = Cell::new("foo bar"); + assert!(format!("{}", x).contains(x.get())); + + x.set("baz qux"); + assert!(format!("{}", x).contains(x.get())); + } + + #[test] + fn double_imm_borrow() { + let x = RefCell::new(0); + let _b1 = x.borrow(); + x.borrow(); + } + + #[test] + fn no_mut_then_imm_borrow() { + let x = RefCell::new(0); + let _b1 = x.borrow_mut(); + assert!(x.try_borrow().is_none()); + } + + #[test] + fn no_imm_then_borrow_mut() { + let x = RefCell::new(0); + let _b1 = x.borrow(); + assert!(x.try_borrow_mut().is_none()); + } + + #[test] + fn no_double_borrow_mut() { + let x = RefCell::new(0); + let _b1 = x.borrow_mut(); + assert!(x.try_borrow_mut().is_none()); + } + + #[test] + fn imm_release_borrow_mut() { + let x = RefCell::new(0); + { + let _b1 = x.borrow(); + } + x.borrow_mut(); + } + + #[test] + fn mut_release_borrow_mut() { + let x = RefCell::new(0); + { + let _b1 = x.borrow_mut(); + } + x.borrow(); + } + + #[test] + fn double_borrow_single_release_no_borrow_mut() { + let x = RefCell::new(0); + let _b1 = x.borrow(); + { + let _b2 = x.borrow(); + } + assert!(x.try_borrow_mut().is_none()); + } + + #[test] + #[should_fail] + fn discard_doesnt_unborrow() { + let x = RefCell::new(0); + let _b = x.borrow(); + let _ = _b; + let _b = x.borrow_mut(); + } +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a0938c83eca..550dcc1fed8 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -67,11 +67,12 @@ mod unicode; mod unit; pub mod any; pub mod bool; +pub mod cell; +pub mod char; pub mod finally; pub mod iter; pub mod option; pub mod raw; -pub mod char; pub mod result; pub mod slice; pub mod str; diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs deleted file mode 100644 index 1e4faf1a899..00000000000 --- a/src/libstd/cell.rs +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright 2012-2013 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. - -//! Types dealing with dynamic mutability - -use clone::Clone; -use cmp::Eq; -use fmt; -use kinds::{marker, Copy}; -use ops::{Deref, DerefMut, Drop}; -use option::{None, Option, Some}; -use ty::Unsafe; - -/// A mutable memory location that admits only `Copy` data. -pub struct Cell { - value: Unsafe, - noshare: marker::NoShare, -} - -impl Cell { - /// Creates a new `Cell` containing the given value. - pub fn new(value: T) -> Cell { - Cell { - value: Unsafe::new(value), - noshare: marker::NoShare, - } - } - - /// Returns a copy of the contained value. - #[inline] - pub fn get(&self) -> T { - unsafe{ *self.value.get() } - } - - /// Sets the contained value. - #[inline] - pub fn set(&self, value: T) { - unsafe { - *self.value.get() = value; - } - } -} - -impl Clone for Cell { - fn clone(&self) -> Cell { - Cell::new(self.get()) - } -} - -impl Eq for Cell { - fn eq(&self, other: &Cell) -> bool { - self.get() == other.get() - } -} - -impl fmt::Show for Cell { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f.buf, r"Cell \{ value: {} \}", self.get()) - } -} - -/// A mutable memory location with dynamically checked borrow rules -pub struct RefCell { - value: Unsafe, - borrow: Cell, - nocopy: marker::NoCopy, - noshare: marker::NoShare, -} - -// Values [1, MAX-1] represent the number of `Ref` active -// (will not outgrow its range since `uint` is the size of the address space) -type BorrowFlag = uint; -static UNUSED: BorrowFlag = 0; -static WRITING: BorrowFlag = -1; - -impl RefCell { - /// Create a new `RefCell` containing `value` - pub fn new(value: T) -> RefCell { - RefCell { - value: Unsafe::new(value), - borrow: Cell::new(UNUSED), - nocopy: marker::NoCopy, - noshare: marker::NoShare, - } - } - - /// Consumes the `RefCell`, returning the wrapped value. - pub fn unwrap(self) -> T { - debug_assert!(self.borrow.get() == UNUSED); - unsafe{self.value.unwrap()} - } - - /// Attempts to immutably borrow the wrapped value. - /// - /// The borrow lasts until the returned `Ref` exits scope. Multiple - /// immutable borrows can be taken out at the same time. - /// - /// Returns `None` if the value is currently mutably borrowed. - pub fn try_borrow<'a>(&'a self) -> Option> { - match self.borrow.get() { - WRITING => None, - borrow => { - self.borrow.set(borrow + 1); - Some(Ref { parent: self }) - } - } - } - - /// Immutably borrows the wrapped value. - /// - /// The borrow lasts until the returned `Ref` exits scope. Multiple - /// immutable borrows can be taken out at the same time. - /// - /// # Failure - /// - /// Fails if the value is currently mutably borrowed. - pub fn borrow<'a>(&'a self) -> Ref<'a, T> { - match self.try_borrow() { - Some(ptr) => ptr, - None => fail!("RefCell already mutably borrowed") - } - } - - /// Mutably borrows the wrapped value. - /// - /// The borrow lasts until the returned `RefMut` exits scope. The value - /// cannot be borrowed while this borrow is active. - /// - /// Returns `None` if the value is currently borrowed. - pub fn try_borrow_mut<'a>(&'a self) -> Option> { - match self.borrow.get() { - UNUSED => { - self.borrow.set(WRITING); - Some(RefMut { parent: self }) - }, - _ => None - } - } - - /// Mutably borrows the wrapped value. - /// - /// The borrow lasts until the returned `RefMut` exits scope. The value - /// cannot be borrowed while this borrow is active. - /// - /// # Failure - /// - /// Fails if the value is currently borrowed. - pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> { - match self.try_borrow_mut() { - Some(ptr) => ptr, - None => fail!("RefCell already borrowed") - } - } -} - -impl Clone for RefCell { - fn clone(&self) -> RefCell { - RefCell::new(self.borrow().clone()) - } -} - -impl Eq for RefCell { - fn eq(&self, other: &RefCell) -> bool { - *self.borrow() == *other.borrow() - } -} - -/// Wraps a borrowed reference to a value in a `RefCell` box. -pub struct Ref<'b, T> { - parent: &'b RefCell -} - -#[unsafe_destructor] -impl<'b, T> Drop for Ref<'b, T> { - fn drop(&mut self) { - let borrow = self.parent.borrow.get(); - debug_assert!(borrow != WRITING && borrow != UNUSED); - self.parent.borrow.set(borrow - 1); - } -} - -impl<'b, T> Deref for Ref<'b, T> { - #[inline] - fn deref<'a>(&'a self) -> &'a T { - unsafe { &*self.parent.value.get() } - } -} - -/// Wraps a mutable borrowed reference to a value in a `RefCell` box. -pub struct RefMut<'b, T> { - parent: &'b RefCell -} - -#[unsafe_destructor] -impl<'b, T> Drop for RefMut<'b, T> { - fn drop(&mut self) { - let borrow = self.parent.borrow.get(); - debug_assert!(borrow == WRITING); - self.parent.borrow.set(UNUSED); - } -} - -impl<'b, T> Deref for RefMut<'b, T> { - #[inline] - fn deref<'a>(&'a self) -> &'a T { - unsafe { &*self.parent.value.get() } - } -} - -impl<'b, T> DerefMut for RefMut<'b, T> { - #[inline] - fn deref_mut<'a>(&'a mut self) -> &'a mut T { - unsafe { &mut *self.parent.value.get() } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn smoketest_cell() { - let x = Cell::new(10); - assert_eq!(x, Cell::new(10)); - assert_eq!(x.get(), 10); - x.set(20); - assert_eq!(x, Cell::new(20)); - assert_eq!(x.get(), 20); - - let y = Cell::new((30, 40)); - assert_eq!(y, Cell::new((30, 40))); - assert_eq!(y.get(), (30, 40)); - } - - #[test] - fn cell_has_sensible_show() { - use str::StrSlice; - - let x = Cell::new("foo bar"); - assert!(format!("{}", x).contains(x.get())); - - x.set("baz qux"); - assert!(format!("{}", x).contains(x.get())); - } - - #[test] - fn double_imm_borrow() { - let x = RefCell::new(0); - let _b1 = x.borrow(); - x.borrow(); - } - - #[test] - fn no_mut_then_imm_borrow() { - let x = RefCell::new(0); - let _b1 = x.borrow_mut(); - assert!(x.try_borrow().is_none()); - } - - #[test] - fn no_imm_then_borrow_mut() { - let x = RefCell::new(0); - let _b1 = x.borrow(); - assert!(x.try_borrow_mut().is_none()); - } - - #[test] - fn no_double_borrow_mut() { - let x = RefCell::new(0); - let _b1 = x.borrow_mut(); - assert!(x.try_borrow_mut().is_none()); - } - - #[test] - fn imm_release_borrow_mut() { - let x = RefCell::new(0); - { - let _b1 = x.borrow(); - } - x.borrow_mut(); - } - - #[test] - fn mut_release_borrow_mut() { - let x = RefCell::new(0); - { - let _b1 = x.borrow_mut(); - } - x.borrow(); - } - - #[test] - fn double_borrow_single_release_no_borrow_mut() { - let x = RefCell::new(0); - let _b1 = x.borrow(); - { - let _b2 = x.borrow(); - } - assert!(x.try_borrow_mut().is_none()); - } - - #[test] - #[should_fail] - fn discard_doesnt_unborrow() { - let x = RefCell::new(0); - let _b = x.borrow(); - let _ = _b; - let _b = x.borrow_mut(); - } -} diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index 8cfc0ae54c3..74ab874d319 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -485,6 +485,7 @@ will look like `"\\{"`. use any; use cast; +use cell::Cell; use char::Char; use cmp; use container::Container; @@ -492,6 +493,7 @@ use io::MemWriter; use io; use iter; use iter::{Iterator, range}; +use kinds::Copy; use num::Signed; use option::{Option, Some, None}; use owned::Box; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 95d67eb77d1..4a555035a08 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -141,6 +141,7 @@ extern crate core; pub use core::any; pub use core::bool; pub use core::cast; +pub use core::cell; pub use core::char; pub use core::clone; pub use core::container; @@ -220,7 +221,6 @@ pub mod hash; /* Common data structures */ pub mod result; -pub mod cell; /* Tasks and communication */ -- cgit 1.4.1-3-g733a5 From 0d8f5fa618da00653897be2050980c800389be82 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 6 May 2014 21:25:36 -0700 Subject: core: Move Option::expect to libstd from libcore See #14008 for more details --- src/libcore/option.rs | 24 ------ src/libcore/should_not_exist.rs | 10 +-- src/libstd/io/timer.rs | 1 + src/libstd/lib.rs | 3 +- src/libstd/option.rs | 167 ++++++++++++++++++++++++++++++++++++++++ src/libstd/prelude.rs | 1 + src/libstd/rt/env.rs | 2 +- src/libstd/vec.rs | 2 +- 8 files changed, 177 insertions(+), 33 deletions(-) create mode 100644 src/libstd/option.rs (limited to 'src/libstd/lib.rs') diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 143e8bf2622..c6884a8002f 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -230,30 +230,6 @@ impl Option { // Getting to contained values ///////////////////////////////////////////////////////////////////////// - /// Unwraps an option, yielding the content of a `Some` - /// - /// # Failure - /// - /// Fails if the value is a `None` with a custom failure message provided by `msg`. - #[inline] - #[cfg(not(test))] - pub fn expect(self, msg: &str) -> T { - match self { - Some(val) => val, - None => fail!(msg), - } - } - - // FIXME: once std::fmt is in libcore, this extra variant should not be - // necessary. - #[cfg(test)] - pub fn expect(self, msg: &str) -> T { - match self { - Some(val) => val, - None => fail!("{}", msg), - } - } - /// Moves a value out of an option type and returns it, consuming the `Option`. /// /// # Failure diff --git a/src/libcore/should_not_exist.rs b/src/libcore/should_not_exist.rs index 587723563eb..50447f0c5b3 100644 --- a/src/libcore/should_not_exist.rs +++ b/src/libcore/should_not_exist.rs @@ -34,7 +34,7 @@ extern { } unsafe fn alloc(cap: uint) -> *mut Vec<()> { - let cap = cap.checked_add(&mem::size_of::>()).expect("cap overflow"); + let cap = cap.checked_add(&mem::size_of::>()).unwrap(); let ret = malloc(cap) as *mut Vec<()>; if ret.is_null() { intrinsics::abort(); @@ -94,7 +94,7 @@ impl FromIterator for ~str { let amt = ch.encode_utf8(tmp); if len + amt > cap { - cap = cap.checked_mul(&2).expect("cap overflow"); + cap = cap.checked_mul(&2).unwrap(); if cap < len + amt { cap = len + amt; } @@ -124,7 +124,7 @@ impl FromIterator for ~str { impl<'a> Add<&'a str,~str> for &'a str { #[inline] fn add(&self, rhs: & &'a str) -> ~str { - let amt = self.len().checked_add(&rhs.len()).expect("len overflow"); + let amt = self.len().checked_add(&rhs.len()).unwrap(); unsafe { let ptr = alloc(amt) as *mut Vec; let base = &mut (*ptr).data as *mut _; @@ -155,7 +155,7 @@ impl FromIterator for ~[A] { fn from_iter>(mut iterator: T) -> ~[A] { let (lower, _) = iterator.size_hint(); let cap = if lower == 0 {16} else {lower}; - let mut cap = cap.checked_mul(&mem::size_of::()).expect("cap overflow"); + let mut cap = cap.checked_mul(&mem::size_of::()).unwrap(); let mut len = 0; unsafe { @@ -163,7 +163,7 @@ impl FromIterator for ~[A] { let mut ret = cast::transmute(ptr); for elt in iterator { if len * mem::size_of::() >= cap { - cap = cap.checked_mul(&2).expect("cap overflow"); + cap = cap.checked_mul(&2).unwrap(); let ptr2 = alloc(cap) as *mut Vec; ptr::copy_nonoverlapping_memory(&mut (*ptr2).data, &(*ptr).data, diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs index 96c4083e7ed..5565918ef85 100644 --- a/src/libstd/io/timer.rs +++ b/src/libstd/io/timer.rs @@ -21,6 +21,7 @@ use comm::Receiver; use io::IoResult; use kinds::Send; use owned::Box; +use option::Expect; use rt::rtio::{IoFactory, LocalIo, RtioTimer}; /// A synchronous timer object diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 4a555035a08..abcc1f099b4 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -149,7 +149,6 @@ pub use core::default; pub use core::intrinsics; pub use core::iter; pub use core::mem; -pub use core::option; pub use core::ptr; pub use core::raw; pub use core::tuple; @@ -221,7 +220,7 @@ pub mod hash; /* Common data structures */ pub mod result; - +pub mod option; /* Tasks and communication */ diff --git a/src/libstd/option.rs b/src/libstd/option.rs new file mode 100644 index 00000000000..17249f567e5 --- /dev/null +++ b/src/libstd/option.rs @@ -0,0 +1,167 @@ +// 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. + +//! Optional values +//! +//! Type `Option` represents an optional value: every `Option` +//! is either `Some` and contains a value, or `None`, and +//! does not. `Option` types are very common in Rust code, as +//! they have a number of uses: +//! +//! * Initial values +//! * Return values for functions that are not defined +//! over their entire input range (partial functions) +//! * Return value for otherwise reporting simple errors, where `None` is +//! returned on error +//! * Optional struct fields +//! * Struct fields that can be loaned or "taken" +//! * Optional function arguments +//! * Nullable pointers +//! * Swapping things out of difficult situations +//! +//! Options are commonly paired with pattern matching to query the presence +//! of a value and take action, always accounting for the `None` case. +//! +//! ``` +//! # // FIXME This is not the greatest first example +//! // cow_says contains the word "moo" +//! let cow_says = Some("moo"); +//! // dog_says does not contain a value +//! let dog_says: Option<&str> = None; +//! +//! // Pattern match to retrieve the value +//! match (cow_says, dog_says) { +//! (Some(cow_words), Some(dog_words)) => { +//! println!("Cow says {} and dog says {}!", cow_words, dog_words); +//! } +//! (Some(cow_words), None) => println!("Cow says {}", cow_words), +//! (None, Some(dog_words)) => println!("Dog says {}", dog_words), +//! (None, None) => println!("Cow and dog are suspiciously silent") +//! } +//! ``` +//! +// +// FIXME: Show how `Option` is used in practice, with lots of methods +// +//! # Options and pointers ("nullable" pointers) +//! +//! Rust's pointer types must always point to a valid location; there are +//! no "null" pointers. Instead, Rust has *optional* pointers, like +//! the optional owned box, `Option<~T>`. +//! +//! The following example uses `Option` to create an optional box of +//! `int`. Notice that in order to use the inner `int` value first the +//! `check_optional` function needs to use pattern matching to +//! determine whether the box has a value (i.e. it is `Some(...)`) or +//! not (`None`). +//! +//! ``` +//! let optional: Option<~int> = None; +//! check_optional(&optional); +//! +//! let optional: Option<~int> = Some(~9000); +//! check_optional(&optional); +//! +//! fn check_optional(optional: &Option<~int>) { +//! match *optional { +//! Some(ref p) => println!("have value {}", p), +//! None => println!("have no value") +//! } +//! } +//! ``` +//! +//! This usage of `Option` to create safe nullable pointers is so +//! common that Rust does special optimizations to make the +//! representation of `Option<~T>` a single pointer. Optional pointers +//! in Rust are stored as efficiently as any other pointer type. +//! +//! # Examples +//! +//! Basic pattern matching on `Option`: +//! +//! ``` +//! let msg = Some("howdy"); +//! +//! // Take a reference to the contained string +//! match msg { +//! Some(ref m) => println!("{}", *m), +//! None => () +//! } +//! +//! // Remove the contained string, destroying the Option +//! let unwrapped_msg = match msg { +//! Some(m) => m, +//! None => "default message" +//! }; +//! ``` +//! +//! Initialize a result to `None` before a loop: +//! +//! ``` +//! enum Kingdom { Plant(uint, &'static str), Animal(uint, &'static str) } +//! +//! // A list of data to search through. +//! let all_the_big_things = [ +//! Plant(250, "redwood"), +//! Plant(230, "noble fir"), +//! Plant(229, "sugar pine"), +//! Animal(25, "blue whale"), +//! Animal(19, "fin whale"), +//! Animal(15, "north pacific right whale"), +//! ]; +//! +//! // We're going to search for the name of the biggest animal, +//! // but to start with we've just got `None`. +//! let mut name_of_biggest_animal = None; +//! let mut size_of_biggest_animal = 0; +//! for big_thing in all_the_big_things.iter() { +//! match *big_thing { +//! Animal(size, name) if size > size_of_biggest_animal => { +//! // Now we've found the name of some big animal +//! size_of_biggest_animal = size; +//! name_of_biggest_animal = Some(name); +//! } +//! Animal(..) | Plant(..) => () +//! } +//! } +//! +//! match name_of_biggest_animal { +//! Some(name) => println!("the biggest animal is {}", name), +//! None => println!("there are no animals :(") +//! } +//! ``` + +use any::Any; +use kinds::Send; + +pub use core::option::{Option, Some, None, Item, collect}; + +/// Extension trait for the `Option` type to add an `expect` method + +// FIXME(#14008) should this trait even exist? +pub trait Expect { + /// Unwraps an option, yielding the content of a `Some` + /// + /// # Failure + /// + /// Fails if the value is a `None` with a custom failure message provided by + /// `msg`. + fn expect(self, m: M) -> T; +} + +impl Expect for Option { + #[inline] + fn expect(self, msg: M) -> T { + match self { + Some(val) => val, + None => fail!(msg), + } + } +} diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 75eb56ffa52..6cd9e96496f 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -65,6 +65,7 @@ pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize}; pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul}; pub use num::{Signed, Unsigned}; pub use num::{Primitive, Int, Float, ToPrimitive, FromPrimitive}; +pub use option::Expect; pub use owned::Box; pub use path::{GenericPath, Path, PosixPath, WindowsPath}; pub use ptr::RawPtr; diff --git a/src/libstd/rt/env.rs b/src/libstd/rt/env.rs index 94f56d42613..708c42030ab 100644 --- a/src/libstd/rt/env.rs +++ b/src/libstd/rt/env.rs @@ -11,7 +11,7 @@ //! Runtime environment settings use from_str::from_str; -use option::{Some, None}; +use option::{Some, None, Expect}; use os; // Note that these are all accessed without any synchronization. diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 35eb5359311..af146b96e50 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -23,7 +23,7 @@ use mem; use num; use num::{CheckedMul, CheckedAdd}; use ops::Drop; -use option::{None, Option, Some}; +use option::{None, Option, Some, Expect}; use ptr::RawPtr; use ptr; use rt::global_heap::{malloc_raw, realloc_raw}; -- cgit 1.4.1-3-g733a5 From 07caa224501817c93be3f5c57a013ed5db6c04e1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 7 May 2014 08:20:22 -0700 Subject: Test fixes and rebase conflicts --- src/doc/rust.md | 2 +- src/libcore/any.rs | 12 ++--------- src/libcore/clone.rs | 5 +++-- src/libcore/cmp.rs | 25 ++++++++++++----------- src/libcore/lib.rs | 4 +++- src/libcore/owned.rs | 38 +++++++++++++++++++++++++++++++++++ src/libstd/comm/mod.rs | 2 -- src/libstd/lib.rs | 7 ++----- src/libstd/option.rs | 10 ++++----- src/libstd/os.rs | 8 +++++--- src/libstd/owned.rs | 33 ------------------------------ src/libstd/repr.rs | 1 - src/libstd/slice.rs | 1 - src/libstd/sync/mpmc_bounded_queue.rs | 1 - 14 files changed, 72 insertions(+), 77 deletions(-) create mode 100644 src/libcore/owned.rs delete mode 100644 src/libstd/owned.rs (limited to 'src/libstd/lib.rs') diff --git a/src/doc/rust.md b/src/doc/rust.md index b6237e2a20f..44e7a304e67 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -3274,7 +3274,7 @@ The machine types are the following: * The signed two's complement word types `i8`, `i16`, `i32` and `i64`, with values drawn from the integer intervals [-(2^(7)), 2^7 - 1], - [-(2^(15)), 2^15 - 1], $[-(2^(31)), 2^31 - 1], [-(2^(63)), 2^63 - 1] + [-(2^(15)), 2^15 - 1], [-(2^(31)), 2^31 - 1], [-(2^(63)), 2^63 - 1] respectively. * The IEEE 754-2008 `binary32` and `binary64` floating-point types: `f32` and diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 0c07bf91bd2..459015445eb 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -149,7 +149,6 @@ mod tests { use prelude::*; use super::*; use owned::Box; - use str::StrSlice; use realstd::str::StrAllocating; #[deriving(Eq, Show)] @@ -275,17 +274,10 @@ mod tests { #[test] fn test_show() { -<<<<<<< HEAD - let a = box 8u as Box; - let b = box Test as Box; + let a = box 8u as Box<::realcore::any::Any>; + let b = box Test as Box<::realcore::any::Any>; assert_eq!(format!("{}", a), "Box".to_owned()); assert_eq!(format!("{}", b), "Box".to_owned()); -======= - let a = ~8u as ~::realcore::any::Any; - let b = ~Test as ~::realcore::any::Any; - assert_eq!(format!("{}", a), "~Any".to_owned()); - assert_eq!(format!("{}", b), "~Any".to_owned()); ->>>>>>> core: Get coretest working let a = &8u as &::realcore::any::Any; let b = &Test as &::realcore::any::Any; diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 659d797bc67..06cbaf19812 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -129,6 +129,7 @@ extern_fn_clone!(A, B, C, D, E, F, G, H) #[cfg(test)] mod test { use prelude::*; + use owned::Box; #[test] fn test_owned_clone() { @@ -154,8 +155,8 @@ mod test { #[test] fn test_clone_from() { - let a = ~5; - let mut b = ~10; + let a = box 5; + let mut b = box 10; b.clone_from(&a); assert_eq!(*b, 5); } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 0ad2a465522..af611cd94e5 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -193,6 +193,7 @@ pub fn max(v1: T, v2: T) -> T { #[cfg(not(test))] mod impls { use cmp::{Ord, TotalOrd, Eq, TotalEq, Ordering}; + use owned::Box; // & pointers impl<'a, T: Eq> Eq for &'a T { @@ -240,28 +241,28 @@ mod impls { } impl TotalEq for @T {} - // ~ pointers - impl Eq for ~T { + // box pointers + impl Eq for Box { #[inline] - fn eq(&self, other: &~T) -> bool { *(*self) == *(*other) } + fn eq(&self, other: &Box) -> bool { *(*self) == *(*other) } #[inline] - fn ne(&self, other: &~T) -> bool { *(*self) != *(*other) } + fn ne(&self, other: &Box) -> bool { *(*self) != *(*other) } } - impl Ord for ~T { + impl Ord for Box { #[inline] - fn lt(&self, other: &~T) -> bool { *(*self) < *(*other) } + fn lt(&self, other: &Box) -> bool { *(*self) < *(*other) } #[inline] - fn le(&self, other: &~T) -> bool { *(*self) <= *(*other) } + fn le(&self, other: &Box) -> bool { *(*self) <= *(*other) } #[inline] - fn ge(&self, other: &~T) -> bool { *(*self) >= *(*other) } + fn ge(&self, other: &Box) -> bool { *(*self) >= *(*other) } #[inline] - fn gt(&self, other: &~T) -> bool { *(*self) > *(*other) } + fn gt(&self, other: &Box) -> bool { *(*self) > *(*other) } } - impl TotalOrd for ~T { + impl TotalOrd for Box { #[inline] - fn cmp(&self, other: &~T) -> Ordering { (**self).cmp(*other) } + fn cmp(&self, other: &Box) -> Ordering { (**self).cmp(*other) } } - impl TotalEq for ~T {} + impl TotalEq for Box {} } #[cfg(test)] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 5aef169cd57..53de765b89c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -27,9 +27,10 @@ #[phase(syntax, link)] #[cfg(test)] extern crate realstd = "std"; #[phase(syntax, link)] #[cfg(test)] extern crate log; -#[cfg(test)] pub use kinds = realcore::kinds; #[cfg(test)] pub use cmp = realcore::cmp; +#[cfg(test)] pub use kinds = realcore::kinds; #[cfg(test)] pub use ops = realcore::ops; +#[cfg(test)] pub use owned = realcore::owned; #[cfg(test)] pub use ty = realcore::ty; #[cfg(not(test))] @@ -73,6 +74,7 @@ pub mod ptr; #[cfg(not(test))] pub mod ops; #[cfg(not(test))] pub mod ty; #[cfg(not(test))] pub mod cmp; +#[cfg(not(test))] pub mod owned; pub mod clone; pub mod default; pub mod container; diff --git a/src/libcore/owned.rs b/src/libcore/owned.rs new file mode 100644 index 00000000000..d5cdd9c39b6 --- /dev/null +++ b/src/libcore/owned.rs @@ -0,0 +1,38 @@ +// 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. + +//! Operations on unique pointer types + +// FIXME: this module should not exist in libcore. It must currently because the +// Box implementation is quite ad-hoc in the compiler. Once there is +// proper support in the compiler this type will be able to be defined in +// its own module. + +/// A value that represents the global exchange heap. This is the default +/// place that the `box` keyword allocates into when no place is supplied. +/// +/// The following two examples are equivalent: +/// +/// let foo = box(HEAP) Bar::new(...); +/// let foo = box Bar::new(...); +#[lang="exchange_heap"] +#[cfg(not(test))] +pub static HEAP: () = (); + +#[cfg(test)] +pub static HEAP: () = (); + +/// A type that represents a uniquely-owned value. +#[lang="owned_box"] +#[cfg(not(test))] +pub struct Box(*T); + +#[cfg(test)] +pub struct Box(*T); diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs index bd1def518f0..df0c6f3b8d3 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/comm/mod.rs @@ -981,7 +981,6 @@ mod test { use native; use os; - use owned::Box; use super::*; pub fn stress_factor() -> uint { @@ -1516,7 +1515,6 @@ mod test { mod sync_tests { use prelude::*; use os; - use owned::Box; pub fn stress_factor() -> uint { match os::getenv("RUST_TEST_STRESS") { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index abcc1f099b4..72d41ae1dd2 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -133,9 +133,10 @@ extern crate core; #[cfg(test)] pub use ty = realstd::ty; #[cfg(test)] pub use owned = realstd::owned; +#[cfg(not(test))] pub use cmp = core::cmp; #[cfg(not(test))] pub use kinds = core::kinds; #[cfg(not(test))] pub use ops = core::ops; -#[cfg(not(test))] pub use cmp = core::cmp; +#[cfg(not(test))] pub use owned = core::owned; #[cfg(not(test))] pub use ty = core::ty; pub use core::any; @@ -206,10 +207,6 @@ pub mod ascii; pub mod rc; pub mod gc; -/* Core language traits */ - -#[cfg(not(test))] pub mod owned; - /* Common traits */ pub mod from_str; diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 17249f567e5..8fbcd529b63 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -54,7 +54,7 @@ //! //! Rust's pointer types must always point to a valid location; there are //! no "null" pointers. Instead, Rust has *optional* pointers, like -//! the optional owned box, `Option<~T>`. +//! the optional owned box, `Option>`. //! //! The following example uses `Option` to create an optional box of //! `int`. Notice that in order to use the inner `int` value first the @@ -63,13 +63,13 @@ //! not (`None`). //! //! ``` -//! let optional: Option<~int> = None; +//! let optional: Option> = None; //! check_optional(&optional); //! -//! let optional: Option<~int> = Some(~9000); +//! let optional: Option> = Some(box 9000); //! check_optional(&optional); //! -//! fn check_optional(optional: &Option<~int>) { +//! fn check_optional(optional: &Option>) { //! match *optional { //! Some(ref p) => println!("have value {}", p), //! None => println!("have no value") @@ -79,7 +79,7 @@ //! //! This usage of `Option` to create safe nullable pointers is so //! common that Rust does special optimizations to make the -//! representation of `Option<~T>` a single pointer. Optional pointers +//! representation of `Option>` a single pointer. Optional pointers //! in Rust are stored as efficiently as any other pointer type. //! //! # Examples diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 47d316f75ab..809757aaf4d 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -81,6 +81,8 @@ pub fn getcwd() -> Path { pub fn getcwd() -> Path { use libc::DWORD; use libc::GetCurrentDirectoryW; + use option::Expect; + let mut buf = [0 as u16, ..BUF_BYTES]; unsafe { if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD { @@ -96,11 +98,11 @@ pub mod win32 { use iter::Iterator; use libc::types::os::arch::extra::DWORD; use libc; - use option::{None, Option}; + use option::{None, Option, Expect}; use option; use os::TMPBUF_SZ; use slice::{MutableVector, ImmutableVector, OwnedVector}; - use str::StrSlice; + use str::{StrSlice, StrAllocating}; use str; use vec::Vec; @@ -182,7 +184,6 @@ pub fn env_as_bytes() -> ~[(~[u8],~[u8])] { #[cfg(windows)] unsafe fn get_env_pairs() -> Vec<~[u8]> { use c_str; - use str::StrSlice; use libc::funcs::extra::kernel32::{ GetEnvironmentStringsA, @@ -830,6 +831,7 @@ fn real_args() -> ~[~str] { #[cfg(windows)] fn real_args() -> ~[~str] { use slice; + use option::Expect; let mut nArgs: c_int = 0; let lpArgCount: *mut c_int = &mut nArgs; diff --git a/src/libstd/owned.rs b/src/libstd/owned.rs deleted file mode 100644 index 4f282c5c9e9..00000000000 --- a/src/libstd/owned.rs +++ /dev/null @@ -1,33 +0,0 @@ -// 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. - -//! Operations on unique pointer types - -/// A value that represents the global exchange heap. This is the default -/// place that the `box` keyword allocates into when no place is supplied. -/// -/// The following two examples are equivalent: -/// -/// let foo = box(HEAP) Bar::new(...); -/// let foo = box Bar::new(...); -#[lang="exchange_heap"] -#[cfg(not(test))] -pub static HEAP: () = (); - -#[cfg(test)] -pub static HEAP: () = (); - -/// A type that represents a uniquely-owned value. -#[lang="owned_box"] -#[cfg(not(test))] -pub struct Box(*T); - -#[cfg(test)] -pub struct Box(*T); diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 2fe4c7eafde..35c5cbc85c3 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -625,7 +625,6 @@ fn test_repr() { use io::stdio::println; use char::is_alphabetic; use mem::swap; - use owned::Box; fn exact_test(t: &T, e:&str) { let mut m = io::MemWriter::new(); diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index 3f5ac535113..c7cefbb28ee 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -1577,7 +1577,6 @@ mod tests { #[test] #[should_fail] fn test_from_elem_fail() { - use cast; use cell::Cell; use rc::Rc; diff --git a/src/libstd/sync/mpmc_bounded_queue.rs b/src/libstd/sync/mpmc_bounded_queue.rs index b392cc8ff9a..2df5031b482 100644 --- a/src/libstd/sync/mpmc_bounded_queue.rs +++ b/src/libstd/sync/mpmc_bounded_queue.rs @@ -162,7 +162,6 @@ impl Clone for Queue { #[cfg(test)] mod tests { use prelude::*; - use option::*; use super::Queue; use native; -- cgit 1.4.1-3-g733a5