diff --git a/src/libcollections/range.rs b/src/libcollections/range.rs index d331ead2c5ee6..268e8520438bc 100644 --- a/src/libcollections/range.rs +++ b/src/libcollections/range.rs @@ -14,79 +14,99 @@ //! Range syntax. -use core::ops::{RangeFull, Range, RangeTo, RangeFrom}; +use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeToInclusive, RangeInclusive}; +use ::Bound; /// **RangeArgument** is implemented by Rust's built-in range types, produced /// by range syntax like `..`, `a..`, `..b` or `c..d`. pub trait RangeArgument { - /// Start index (inclusive) - /// - /// Return start value if present, else `None`. + /// Lower bound of the range /// /// # Examples /// /// ``` /// #![feature(collections)] /// #![feature(collections_range)] + /// #![feature(collections_bound)] /// /// extern crate collections; /// /// # fn main() { /// use collections::range::RangeArgument; + /// use collections::Bound::*; /// - /// assert_eq!((..10).start(), None); - /// assert_eq!((3..10).start(), Some(&3)); + /// assert_eq!((..10).lower(), Unbounded); + /// assert_eq!((3..10).lower(), Included(&3)); /// # } /// ``` - fn start(&self) -> Option<&T> { - None + fn lower(&self) -> Bound<&T> { + Bound::Unbounded } - /// End index (exclusive) - /// - /// Return end value if present, else `None`. + /// Upper bound of the range /// /// # Examples /// /// ``` /// #![feature(collections)] /// #![feature(collections_range)] + /// #![feature(collections_bound)] /// /// extern crate collections; /// /// # fn main() { /// use collections::range::RangeArgument; + /// use collections::Bound::*; /// - /// assert_eq!((3..).end(), None); - /// assert_eq!((3..10).end(), Some(&10)); + /// assert_eq!((3..).upper(), Unbounded); + /// assert_eq!((3..10).upper(), Excluded(&10)); /// # } /// ``` - fn end(&self) -> Option<&T> { - None + fn upper(&self) -> Bound<&T> { + Bound::Unbounded } } -// FIXME add inclusive ranges to RangeArgument - impl RangeArgument for RangeFull {} impl RangeArgument for RangeFrom { - fn start(&self) -> Option<&T> { - Some(&self.start) + fn lower(&self) -> Bound<&T> { + Bound::Included(&self.start) } } impl RangeArgument for RangeTo { - fn end(&self) -> Option<&T> { - Some(&self.end) + fn upper(&self) -> Bound<&T> { + Bound::Excluded(&self.end) + } +} + +impl RangeArgument for RangeToInclusive { + fn upper(&self) -> Bound<&T> { + Bound::Included(&self.end) } } impl RangeArgument for Range { - fn start(&self) -> Option<&T> { - Some(&self.start) + fn lower(&self) -> Bound<&T> { + Bound::Included(&self.start) + } + fn upper(&self) -> Bound<&T> { + Bound::Excluded(&self.end) + } +} + +impl RangeArgument for RangeInclusive { + fn lower(&self) -> Bound<&T> { + match *self { + RangeInclusive::NonEmpty { ref start, .. } => Bound::Included(start), + RangeInclusive::Empty { ref at } => Bound::Included(at), + } } - fn end(&self) -> Option<&T> { - Some(&self.end) + fn upper(&self) -> Bound<&T> { + match *self { + RangeInclusive::NonEmpty { ref end, .. } => Bound::Included(end), + RangeInclusive::Empty { ref at } => Bound::Excluded(at), + } } } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 157c762b4a7ed..9c2ad4868d903 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -71,6 +71,7 @@ use range::RangeArgument; use str::{self, FromStr, Utf8Error, Chars}; use vec::Vec; use boxed::Box; +use ::Bound; /// A UTF-8 encoded, growable string. /// @@ -1349,9 +1350,16 @@ impl String { // of the vector version. The data is just plain bytes. // Because the range removal happens in Drop, if the Drain iterator is leaked, // the removal will not happen. - let len = self.len(); - let start = *range.start().unwrap_or(&0); - let end = *range.end().unwrap_or(&len); + let start = match range.lower() { + Bound::Included(&start) => start, + Bound::Excluded(&start) => start + 1, + Bound::Unbounded => 0, + }; + let end = match range.upper() { + Bound::Included(&end) => end + 1, + Bound::Excluded(&end) => end, + Bound::Unbounded => self.len(), + }; // Take out two simultaneous borrows. The &mut String won't be accessed // until iteration is over, in Drop. diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 27cf0268c99bb..82a51966bb5e9 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -84,6 +84,7 @@ use core::ptr::Shared; use core::slice; use super::range::RangeArgument; +use ::Bound; /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// @@ -1060,8 +1061,16 @@ impl Vec { // the hole, and the vector length is restored to the new length. // let len = self.len(); - let start = *range.start().unwrap_or(&0); - let end = *range.end().unwrap_or(&len); + let start = match range.lower() { + Bound::Included(&start) => start, + Bound::Excluded(&start) => start + 1, + Bound::Unbounded => 0, + }; + let end = match range.upper() { + Bound::Included(&end) => end + 1, + Bound::Excluded(&end) => end, + Bound::Unbounded => len, + }; assert!(start <= end); assert!(end <= len); diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 76e44c815793f..908fa1c4dffe4 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -34,6 +34,7 @@ use alloc::raw_vec::RawVec; use super::range::RangeArgument; use super::vec::Vec; +use super::Bound; const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 const MINIMUM_CAPACITY: usize = 1; // 2 - 1 @@ -852,8 +853,16 @@ impl VecDeque { // and the head/tail values will be restored correctly. // let len = self.len(); - let start = *range.start().unwrap_or(&0); - let end = *range.end().unwrap_or(&len); + let start = match range.lower() { + Bound::Included(&start) => start, + Bound::Excluded(&start) => start + 1, + Bound::Unbounded => 0, + }; + let end = match range.upper() { + Bound::Included(&end) => end + 1, + Bound::Excluded(&end) => end, + Bound::Unbounded => len, + }; assert!(start <= end, "drain lower bound was too large"); assert!(end <= len, "drain upper bound was too large"); diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index 844e9041d2029..c84be0df5e9cc 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -19,6 +19,7 @@ use std::slice; use std::fmt; use std::mem; use std::collections::range::RangeArgument; +use std::collections::Bound; pub unsafe trait Array { type Element; @@ -119,8 +120,16 @@ impl ArrayVec { // the hole, and the vector length is restored to the new length. // let len = self.len(); - let start = *range.start().unwrap_or(&0); - let end = *range.end().unwrap_or(&len); + let start = match range.lower() { + Bound::Included(&start) => start, + Bound::Excluded(&start) => start + 1, + Bound::Unbounded => 0, + }; + let end = match range.upper() { + Bound::Included(&end) => end + 1, + Bound::Excluded(&end) => end, + Bound::Unbounded => len, + }; assert!(start <= end); assert!(end <= len); @@ -316,4 +325,3 @@ impl Default for ManuallyDrop { ManuallyDrop::new() } } - diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 4623e52ffc2fd..14ff4b236df9f 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -35,6 +35,7 @@ #![feature(untagged_unions)] #![feature(associated_consts)] #![feature(unsize)] +#![feature(collections_bound)] #![cfg_attr(unix, feature(libc))] #![cfg_attr(test, feature(test))]