From 328818934b3cc3a19c29fd4f87f165808bf9c037 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sat, 18 Feb 2017 18:57:18 +0000 Subject: [PATCH 1/3] impl RangeArgument for RangeInclusive and add appropriate tests --- src/libcollections/range.rs | 18 +++++++++++- src/libcollectionstest/btree/map.rs | 27 +++++++++++++++++ src/libcollectionstest/lib.rs | 1 + src/libcollectionstest/vec.rs | 45 +++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) diff --git a/src/libcollections/range.rs b/src/libcollections/range.rs index 1df4ace377707..e62df03f4fbe0 100644 --- a/src/libcollections/range.rs +++ b/src/libcollections/range.rs @@ -14,7 +14,7 @@ //! Range syntax. -use core::ops::{RangeFull, Range, RangeTo, RangeFrom}; +use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive}; use Bound::{self, Excluded, Included, Unbounded}; /// **RangeArgument** is implemented by Rust's built-in range types, produced @@ -105,6 +105,22 @@ impl RangeArgument for Range { } } +#[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), + } + } +} + impl RangeArgument for (Bound, Bound) { fn start(&self) -> Bound<&T> { match *self { diff --git a/src/libcollectionstest/btree/map.rs b/src/libcollectionstest/btree/map.rs index f33923f996319..9d8895b79da2e 100644 --- a/src/libcollectionstest/btree/map.rs +++ b/src/libcollectionstest/btree/map.rs @@ -178,6 +178,33 @@ fn test_range_small() { assert_eq!(j, size - 2); } +#[test] +fn test_range_inclusive() { + let size = 500; + + let map: BTreeMap<_, _> = (0...size).map(|i| (i, i)).collect(); + + fn check<'a, L, R>(lhs: L, rhs: R) + where L: IntoIterator, + R: IntoIterator, + { + let lhs: Vec<_> = lhs.into_iter().collect(); + let rhs: Vec<_> = rhs.into_iter().collect(); + assert_eq!(lhs, rhs); + } + + check(map.range(size + 1...size + 1), vec![]); + check(map.range(size...size), vec![(&size, &size)]); + check(map.range(size...size + 1), vec![(&size, &size)]); + check(map.range(0...0), vec![(&0, &0)]); + check(map.range(0...size - 1), map.range(..size)); + check(map.range(-1...-1), vec![]); + check(map.range(-1...size), map.range(..)); + check(map.range(5...8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]); + check(map.range(-1...0), vec![(&0, &0)]); + check(map.range(-1...2), vec![(&0, &0), (&1, &1), (&2, &2)]); +} + #[test] fn test_range_equal_empty_cases() { let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 57e3c2df059e1..849d240169169 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -14,6 +14,7 @@ #![feature(binary_heap_peek_mut_pop)] #![feature(box_syntax)] #![feature(btree_range)] +#![feature(inclusive_range_syntax)] #![feature(collection_placement)] #![feature(collections)] #![feature(collections_bound)] diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index edeedf1d40baf..ef3ab964f77ee 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -507,6 +507,51 @@ fn test_drain_range() { assert_eq!(v, &[(), ()]); } +#[test] +fn test_drain_inclusive_range() { + let mut v = vec!['a', 'b', 'c', 'd', 'e']; + for _ in v.drain(1...3) { + } + assert_eq!(v, &['a', 'e']); + + let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect(); + for _ in v.drain(1...5) { + } + assert_eq!(v, &["0".to_string()]); + + let mut v: Vec = (0...5).map(|x| x.to_string()).collect(); + for _ in v.drain(0...5) { + } + assert_eq!(v, Vec::::new()); + + let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect(); + for _ in v.drain(0...3) { + } + assert_eq!(v, &["4".to_string(), "5".to_string()]); +} + +#[test] +fn test_drain_max_vec_size() { + let mut v = Vec::<()>::with_capacity(usize::max_value()); + unsafe { v.set_len(usize::max_value()); } + for _ in v.drain(usize::max_value() - 1..) { + } + assert_eq!(v.len(), usize::max_value() - 1); + + let mut v = Vec::<()>::with_capacity(usize::max_value()); + unsafe { v.set_len(usize::max_value()); } + for _ in v.drain(usize::max_value() - 1...usize::max_value() - 1) { + } + assert_eq!(v.len(), usize::max_value() - 1); +} + +#[test] +#[should_panic] +fn test_drain_inclusive_out_of_bounds() { + let mut v = vec![1, 2, 3, 4, 5]; + v.drain(5...5); +} + #[test] fn test_into_boxed_slice() { let xs = vec![1, 2, 3]; From 65c876f2d30ddbd316849dc9092eb2b7b20bdff9 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sat, 18 Feb 2017 19:09:11 +0000 Subject: [PATCH 2/3] add test for max value --- src/libcollectionstest/btree/map.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libcollectionstest/btree/map.rs b/src/libcollectionstest/btree/map.rs index 9d8895b79da2e..0fa73b1934365 100644 --- a/src/libcollectionstest/btree/map.rs +++ b/src/libcollectionstest/btree/map.rs @@ -205,6 +205,14 @@ fn test_range_inclusive() { check(map.range(-1...2), vec![(&0, &0), (&1, &1), (&2, &2)]); } +#[test] +fn test_range_inclusive_max_value() { + let max = ::std::usize::MAX; + let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect(); + + assert_eq!(map.range(max...max).collect::>(), &[(&max, &0)]); +} + #[test] fn test_range_equal_empty_cases() { let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); From 43382903a19ce209dee136e5f983003062b7ce78 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sat, 18 Feb 2017 20:58:12 +0000 Subject: [PATCH 3/3] add impl for RangeToInclusive --- src/libcollections/range.rs | 12 +++++++++++- src/libcollectionstest/btree/map.rs | 2 ++ src/libcollectionstest/vec.rs | 5 +++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/libcollections/range.rs b/src/libcollections/range.rs index e62df03f4fbe0..e4b94a1d70ee4 100644 --- a/src/libcollections/range.rs +++ b/src/libcollections/range.rs @@ -14,7 +14,7 @@ //! Range syntax. -use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive}; +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 @@ -121,6 +121,16 @@ impl RangeArgument for RangeInclusive { } } +#[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 { diff --git a/src/libcollectionstest/btree/map.rs b/src/libcollectionstest/btree/map.rs index 0fa73b1934365..2c899d96940ec 100644 --- a/src/libcollectionstest/btree/map.rs +++ b/src/libcollectionstest/btree/map.rs @@ -200,6 +200,8 @@ fn test_range_inclusive() { check(map.range(0...size - 1), map.range(..size)); check(map.range(-1...-1), vec![]); check(map.range(-1...size), map.range(..)); + check(map.range(...size), map.range(..)); + check(map.range(...200), map.range(..201)); check(map.range(5...8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]); check(map.range(-1...0), vec![(&0, &0)]); check(map.range(-1...2), vec![(&0, &0), (&1, &1), (&2, &2)]); diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index ef3ab964f77ee..06d70800d3925 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -528,6 +528,11 @@ fn test_drain_inclusive_range() { for _ in v.drain(0...3) { } assert_eq!(v, &["4".to_string(), "5".to_string()]); + + let mut v: Vec<_> = (0...1).map(|x| x.to_string()).collect(); + for _ in v.drain(...0) { + } + assert_eq!(v, &["1".to_string()]); } #[test]