diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 3bea61f6220b6..41124220f69e4 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -136,60 +136,11 @@ mod std { pub use core::ops; // RangeFull } -/// An endpoint of a range of keys. -/// -/// # Examples -/// -/// `Bound`s are range endpoints: -/// -/// ``` -/// #![feature(collections_range)] -/// -/// use std::collections::range::RangeArgument; -/// use std::collections::Bound::*; -/// -/// assert_eq!((..100).start(), Unbounded); -/// assert_eq!((1..12).start(), Included(&1)); -/// assert_eq!((1..12).end(), Excluded(&12)); -/// ``` -/// -/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. -/// Note that in most cases, it's better to use range syntax (`1..5`) instead. -/// -/// ``` -/// use std::collections::BTreeMap; -/// use std::collections::Bound::{Excluded, Included, Unbounded}; -/// -/// let mut map = BTreeMap::new(); -/// map.insert(3, "a"); -/// map.insert(5, "b"); -/// map.insert(8, "c"); -/// -/// for (key, value) in map.range((Excluded(3), Included(8))) { -/// println!("{}: {}", key, value); -/// } -/// -/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); -/// ``` -/// -/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range -#[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub enum Bound { - /// An inclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Included(T), - /// An exclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Excluded(T), - /// An infinite endpoint. Indicates that there is no bound in this direction. - #[stable(feature = "collections_bound", since = "1.17.0")] - Unbounded, -} - /// An intermediate trait for specialization of `Extend`. #[doc(hidden)] trait SpecExtend { /// Extends `self` with the contents of the given iterator. fn spec_extend(&mut self, iter: I); } + +pub use core::ops::Bound; diff --git a/src/libcollections/range.rs b/src/libcollections/range.rs index 8f3209d015b15..3d0f47391f82b 100644 --- a/src/libcollections/range.rs +++ b/src/libcollections/range.rs @@ -8,151 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![unstable(feature = "collections_range", - reason = "waiting for dust to settle on inclusive ranges", - issue = "30877")] //! Range syntax. -use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive, RangeToInclusive}; -use Bound::{self, Excluded, Included, Unbounded}; - -/// `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 bound. - /// - /// Returns the start value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// #![feature(collections)] - /// #![feature(collections_range)] - /// - /// extern crate collections; - /// - /// # fn main() { - /// use collections::range::RangeArgument; - /// use collections::Bound::*; - /// - /// assert_eq!((..10).start(), Unbounded); - /// assert_eq!((3..10).start(), Included(&3)); - /// # } - /// ``` - fn start(&self) -> Bound<&T>; - - /// End index bound. - /// - /// Returns the end value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// #![feature(collections)] - /// #![feature(collections_range)] - /// - /// extern crate collections; - /// - /// # fn main() { - /// use collections::range::RangeArgument; - /// use collections::Bound::*; - /// - /// assert_eq!((3..).end(), Unbounded); - /// assert_eq!((3..10).end(), Excluded(&10)); - /// # } - /// ``` - fn end(&self) -> Bound<&T>; -} - -// FIXME add inclusive ranges to RangeArgument - -impl RangeArgument for RangeFull { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -impl RangeArgument for RangeFrom { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -impl RangeArgument for RangeTo { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -impl RangeArgument for Range { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeInclusive { - fn start(&self) -> Bound<&T> { - match *self { - RangeInclusive::Empty{ ref at } => Included(at), - RangeInclusive::NonEmpty { ref start, .. } => Included(start), - } - } - fn end(&self) -> Bound<&T> { - match *self { - RangeInclusive::Empty{ ref at } => Excluded(at), - RangeInclusive::NonEmpty { ref end, .. } => Included(end), - } - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeToInclusive { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -impl RangeArgument for (Bound, Bound) { - fn start(&self) -> Bound<&T> { - match *self { - (Included(ref start), _) => Included(start), - (Excluded(ref start), _) => Excluded(start), - (Unbounded, _) => Unbounded, - } - } - - fn end(&self) -> Bound<&T> { - match *self { - (_, Included(ref end)) => Included(end), - (_, Excluded(ref end)) => Excluded(end), - (_, Unbounded) => Unbounded, - } - } -} - -impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { - fn start(&self) -> Bound<&T> { - self.0 - } - - fn end(&self) -> Bound<&T> { - self.1 - } -} +pub use core::ops::RangeArgument; diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 175b3a5a69ac1..0d640d955e52d 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -2381,6 +2381,220 @@ impl> RangeToInclusive { // RangeToInclusive cannot impl From> // because underflow would be possible with (..0).into() + +/// An endpoint of a range of keys. +/// +/// # Examples +/// +/// `Bound`s are range endpoints: +/// +/// ``` +/// #![feature(collections_range)] +/// +/// use std::collections::range::RangeArgument; +/// use std::collections::Bound::*; +/// +/// assert_eq!((..100).start(), Unbounded); +/// assert_eq!((1..12).start(), Included(&1)); +/// assert_eq!((1..12).end(), Excluded(&12)); +/// ``` +/// +/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. +/// Note that in most cases, it's better to use range syntax (`1..5`) instead. +/// +/// ``` +/// use std::collections::BTreeMap; +/// use std::collections::Bound::{Excluded, Included, Unbounded}; +/// +/// let mut map = BTreeMap::new(); +/// map.insert(3, "a"); +/// map.insert(5, "b"); +/// map.insert(8, "c"); +/// +/// for (key, value) in map.range((Excluded(3), Included(8))) { +/// println!("{}: {}", key, value); +/// } +/// +/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); +/// ``` +/// +/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range +#[stable(feature = "collections_bound", since = "1.17.0")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included(T), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded(T), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, +} + +/// `RangeArgument` is implemented by Rust's built-in range types, produced +/// by range syntax like `..`, `a..`, `..b` or `c..d`. +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +pub trait RangeArgument { + /// Start index bound. + /// + /// Returns the start value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// #![feature(collections)] + /// #![feature(collections_range)] + /// + /// extern crate collections; + /// + /// # fn main() { + /// use collections::range::RangeArgument; + /// use collections::Bound::*; + /// + /// assert_eq!((..10).start(), Unbounded); + /// assert_eq!((3..10).start(), Included(&3)); + /// # } + /// ``` + fn start(&self) -> Bound<&T>; + + /// End index bound. + /// + /// Returns the end value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// #![feature(collections)] + /// #![feature(collections_range)] + /// + /// extern crate collections; + /// + /// # fn main() { + /// use collections::range::RangeArgument; + /// use collections::Bound::*; + /// + /// assert_eq!((3..).end(), Unbounded); + /// assert_eq!((3..10).end(), Excluded(&10)); + /// # } + /// ``` + fn end(&self) -> Bound<&T>; +} + +// FIXME add inclusive ranges to RangeArgument + +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +impl RangeArgument for RangeFull { + fn start(&self) -> Bound<&T> { + Bound::Unbounded + } + fn end(&self) -> Bound<&T> { + Bound::Unbounded + } +} + +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +impl RangeArgument for RangeFrom { + fn start(&self) -> Bound<&T> { + Bound::Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Bound::Unbounded + } +} + +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +impl RangeArgument for RangeTo { + fn start(&self) -> Bound<&T> { + Bound::Unbounded + } + fn end(&self) -> Bound<&T> { + Bound::Excluded(&self.end) + } +} + +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +impl RangeArgument for Range { + fn start(&self) -> Bound<&T> { + Bound::Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Bound::Excluded(&self.end) + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl RangeArgument for RangeInclusive { + fn start(&self) -> Bound<&T> { + match *self { + RangeInclusive::Empty{ ref at } => Bound::Included(at), + RangeInclusive::NonEmpty { ref start, .. } => Bound::Included(start), + } + } + fn end(&self) -> Bound<&T> { + match *self { + RangeInclusive::Empty{ ref at } => Bound::Excluded(at), + RangeInclusive::NonEmpty { ref end, .. } => Bound::Included(end), + } + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl RangeArgument for RangeToInclusive { + fn start(&self) -> Bound<&T> { + Bound::Unbounded + } + fn end(&self) -> Bound<&T> { + Bound::Included(&self.end) + } +} + +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +impl RangeArgument for (Bound, Bound) { + fn start(&self) -> Bound<&T> { + match *self { + (Bound::Included(ref start), _) => Bound::Included(start), + (Bound::Excluded(ref start), _) => Bound::Excluded(start), + (Bound::Unbounded, _) => Bound::Unbounded, + } + } + + fn end(&self) -> Bound<&T> { + match *self { + (_, Bound::Included(ref end)) => Bound::Included(end), + (_, Bound::Excluded(ref end)) => Bound::Excluded(end), + (_, Bound::Unbounded) => Bound::Unbounded, + } + } +} + +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { + fn start(&self) -> Bound<&T> { + self.0 + } + + fn end(&self) -> Bound<&T> { + self.1 + } +} + + /// The `Deref` trait is used to specify the functionality of dereferencing /// operations, like `*v`. ///