aboutsummaryrefslogtreecommitdiff
path: root/src/index.rs
diff options
context:
space:
mode:
authorJoe Wilm <jwilm@users.noreply.github.com>2017-01-06 21:51:24 -0800
committerGitHub <noreply@github.com>2017-01-06 21:51:24 -0800
commit852c2d8f15bfc11f0222fa08626c38724accd35a (patch)
tree0880b8e38d76ae4ba0fb1772fbd11cae53168729 /src/index.rs
parent62739bd226974358a811b4680b4b74c268418f5b (diff)
parent4e1f4c8cd7180606156b71ad0222f60e4559f2b3 (diff)
downloadr-alacritty-852c2d8f15bfc11f0222fa08626c38724accd35a.tar.gz
r-alacritty-852c2d8f15bfc11f0222fa08626c38724accd35a.tar.bz2
r-alacritty-852c2d8f15bfc11f0222fa08626c38724accd35a.zip
Merge pull request #131 from Manishearth/stable
Make it compile on stable Rust (almost)
Diffstat (limited to 'src/index.rs')
-rw-r--r--src/index.rs182
1 files changed, 153 insertions, 29 deletions
diff --git a/src/index.rs b/src/index.rs
index c80589da..25d5eaff 100644
--- a/src/index.rs
+++ b/src/index.rs
@@ -17,9 +17,7 @@
/// Indexing types and implementations for Grid and Line
use std::cmp::{Ord, Ordering};
use std::fmt;
-use std::iter::Step;
-use std::mem;
-use std::ops::{self, Deref, Add};
+use std::ops::{self, Deref, Add, Range};
/// The side of a cell
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
@@ -46,7 +44,7 @@ impl Ord for Point {
use std::cmp::Ordering::*;
match (self.line.cmp(&other.line), self.col.cmp(&other.col)) {
(Equal, Equal) => Equal,
- (Equal, ord) => ord,
+ (Equal, ord) |
(ord, Equal) => ord,
(Less, _) => Less,
(Greater, _) => Greater,
@@ -200,6 +198,128 @@ macro_rules! sub {
}
}
+/// This exists because we can't implement Iterator on Range
+/// and the existing impl needs the unstable Step trait
+/// This should be removed and replaced with a Step impl
+/// in the ops macro when `step_by` is stabilized
+pub struct IndexRange<T>(pub Range<T>);
+
+impl<T> From<Range<T>> for IndexRange<T> {
+ fn from(from: Range<T>) -> Self {
+ IndexRange(from)
+ }
+}
+
+pub enum RangeInclusive<Idx> {
+ Empty {
+ at: Idx,
+ },
+ NonEmpty {
+ start: Idx,
+ end: Idx,
+ },
+}
+
+impl<Idx> RangeInclusive<Idx> {
+ pub fn new(from: Idx, to: Idx) -> Self {
+ RangeInclusive::NonEmpty {
+ start: from,
+ end: to
+ }
+ }
+}
+
+macro_rules! inclusive {
+ ($ty:ty, $steps_add_one:expr) => {
+ // impl copied from stdlib, can be removed when inclusive_range is stabilized
+ impl Iterator for RangeInclusive<$ty> {
+ type Item = $ty;
+
+ #[inline]
+ fn next(&mut self) -> Option<$ty> {
+ use index::RangeInclusive::*;
+
+ // this function has a sort of odd structure due to borrowck issues
+ // we may need to replace self.range, so borrows of start and end need to end early
+
+ let at_end;
+ match *self {
+ Empty { .. } => return None, // empty iterators yield no values
+
+ NonEmpty { ref mut start, ref mut end } => {
+
+ // march start towards (maybe past!) end and yield the old value
+ if start <= end {
+ let old = *start;
+ *start = old + 1;
+ return Some(old);
+ }
+ at_end = *end;
+ }
+ };
+
+ // got this far; the range is empty, replace it
+ *self = Empty { at: at_end };
+ None
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ use index::RangeInclusive::*;
+
+ match *self {
+ Empty { .. } => (0, Some(0)),
+
+ NonEmpty { ref start, ref end } => {
+ let added = $steps_add_one(start, end);
+ match added {
+ Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
+ None => (0, None)
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+fn steps_add_one_u8(start: &u8, end: &u8) -> Option<usize> {
+ if *start < *end {
+ Some((*end - *start) as usize)
+ } else {
+ None
+ }
+}
+inclusive!(u8, steps_add_one_u8);
+
+#[test]
+fn test_range() {
+ assert_eq!(RangeInclusive::new(1,10).collect::<Vec<_>>(),
+ vec![1,2,3,4,5,6,7,8,9,10]);
+}
+
+// can be removed if range_contains is stabilized
+pub trait Contains {
+ type Content;
+ fn contains_(&self, item: Self::Content) -> bool;
+}
+
+impl<T: PartialOrd<T>> Contains for Range<T> {
+ type Content = T;
+ fn contains_(&self, item: Self::Content) -> bool {
+ (self.start <= item) && (item < self.end)
+ }
+}
+
+impl<T: PartialOrd<T>> Contains for RangeInclusive<T> {
+ type Content = T;
+ fn contains_(&self, item: Self::Content) -> bool {
+ if let RangeInclusive::NonEmpty{ref start, ref end} = *self {
+ (*start <= item) && (item <= *end)
+ } else { false }
+ }
+}
+
macro_rules! ops {
($ty:ty, $construct:expr) => {
add!($ty, $construct);
@@ -207,12 +327,7 @@ macro_rules! ops {
deref!($ty, usize);
forward_ref_binop!(impl Add, add for $ty, $ty);
- impl Step for $ty {
- #[inline]
- fn step(&self, by: &$ty) -> Option<$ty> {
- Some(*self + *by)
- }
-
+ impl $ty {
#[inline]
#[allow(trivial_numeric_casts)]
fn steps_between(start: &$ty, end: &$ty, by: &$ty) -> Option<usize> {
@@ -233,36 +348,45 @@ macro_rules! ops {
#[inline]
fn steps_between_by_one(start: &$ty, end: &$ty) -> Option<usize> {
- Step::steps_between(start, end, &$construct(1))
- }
-
- #[inline]
- #[allow(unused_comparisons)]
- fn is_negative(&self) -> bool {
- self.0 < 0
+ Self::steps_between(start, end, &$construct(1))
}
+ }
+ impl Iterator for IndexRange<$ty> {
+ type Item = $ty;
#[inline]
- fn replace_one(&mut self) -> Self {
- mem::replace(self, $construct(0))
+ fn next(&mut self) -> Option<$ty> {
+ if self.0.start < self.0.end {
+ let old = self.0.start;
+ self.0.start = old + 1;
+ Some(old)
+ } else {
+ None
+ }
}
-
#[inline]
- fn replace_zero(&mut self) -> Self {
- mem::replace(self, $construct(1))
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ match Self::Item::steps_between_by_one(&self.0.start, &self.0.end) {
+ Some(hint) => (hint, Some(hint)),
+ None => (0, None)
+ }
}
+ }
- #[inline]
- fn add_one(&self) -> Self {
- *self + 1
- }
+ inclusive!($ty, <$ty>::steps_between_by_one);
+ impl DoubleEndedIterator for IndexRange<$ty> {
#[inline]
- fn sub_one(&self) -> Self {
- *self - 1
+ fn next_back(&mut self) -> Option<$ty> {
+ if self.0.start < self.0.end {
+ let new = self.0.end - 1;
+ self.0.end = new;
+ Some(new)
+ } else {
+ None
+ }
}
}
-
impl ops::AddAssign<$ty> for $ty {
#[inline]
fn add_assign(&mut self, rhs: $ty) {