Make RangeIndex trait more general

This commit is contained in:
Brendan Zabarauskas 2014-05-14 15:41:00 -07:00
parent 309c9db2ac
commit 2e37b5e8fe
3 changed files with 63 additions and 55 deletions

View file

@ -4,7 +4,7 @@
use servo_util::vec::*; use servo_util::vec::*;
use servo_util::range; use servo_util::range;
use servo_util::range::{Range, RangeIndex, EachIndex}; use servo_util::range::{Range, RangeIndex, IntRangeIndex, EachIndex};
use servo_util::geometry::Au; use servo_util::geometry::Au;
use std::cmp::{Ord, Eq}; use std::cmp::{Ord, Eq};
@ -526,7 +526,7 @@ pub struct GlyphStore {
is_whitespace: bool, is_whitespace: bool,
} }
range_index! { int_range_index! {
#[doc = "An index that refers to a character in a text run. This could \ #[doc = "An index that refers to a character in a text run. This could \
point to the middle of a glyph."] point to the middle of a glyph."]
struct CharIndex(int) struct CharIndex(int)

View file

@ -20,7 +20,7 @@ use gfx::font::FontMetrics;
use gfx::font_context::FontContext; use gfx::font_context::FontContext;
use servo_util::geometry::Au; use servo_util::geometry::Au;
use servo_util::geometry; use servo_util::geometry;
use servo_util::range::{Range, RangeIndex}; use servo_util::range::{Range, RangeIndex, IntRangeIndex};
use std::iter::Enumerate; use std::iter::Enumerate;
use std::fmt; use std::fmt;
use std::mem; use std::mem;
@ -61,7 +61,7 @@ pub struct LineBox {
pub green_zone: Size2D<Au> pub green_zone: Size2D<Au>
} }
range_index! { int_range_index! {
struct BoxIndex(int) struct BoxIndex(int)
} }
@ -981,7 +981,7 @@ impl fmt::Show for InlineFlow {
} }
} }
range_index! { int_range_index! {
#[doc = "The index of a DOM element into the flat list of fragments."] #[doc = "The index of a DOM element into the flat list of fragments."]
struct FragmentIndex(int) struct FragmentIndex(int)
} }

View file

@ -9,21 +9,26 @@ use std::num;
use std::num::{Bounded, Zero}; use std::num::{Bounded, Zero};
/// An index type to be used by a `Range` /// An index type to be used by a `Range`
pub trait RangeIndex<T>: Eq + Ord pub trait RangeIndex: Copy
+ Clone + Clone
+ Copy + fmt::Show
+ Zero + Eq
+ Ord
+ TotalEq + TotalEq
+ TotalOrd + TotalOrd
+ Add<Self, Self> + Add<Self, Self>
+ Sub<Self, Self> + Sub<Self, Self>
+ Neg<Self> + Neg<Self>
+ fmt::Show { + Zero {}
pub trait IntRangeIndex<T>: RangeIndex + Copy {
fn new(x: T) -> Self; fn new(x: T) -> Self;
fn get(self) -> T; fn get(self) -> T;
} }
impl RangeIndex<int> for int { impl RangeIndex for int {}
impl IntRangeIndex<int> for int {
#[inline] #[inline]
fn new(x: int) -> int { x } fn new(x: int) -> int { x }
@ -33,7 +38,7 @@ impl RangeIndex<int> for int {
/// Implements a range index type with operator overloads /// Implements a range index type with operator overloads
#[macro_export] #[macro_export]
macro_rules! range_index { macro_rules! int_range_index {
($(#[$attr:meta])* struct $Self:ident($T:ty)) => ( ($(#[$attr:meta])* struct $Self:ident($T:ty)) => (
#[deriving(Clone, Eq, Ord, TotalEq, TotalOrd, Show, Zero)] #[deriving(Clone, Eq, Ord, TotalEq, TotalOrd, Show, Zero)]
$(#[$attr])* $(#[$attr])*
@ -46,7 +51,9 @@ macro_rules! range_index {
} }
} }
impl RangeIndex<$T> for $Self { impl RangeIndex for $Self {}
impl IntRangeIndex<$T> for $Self {
#[inline] #[inline]
fn new(x: $T) -> $Self { fn new(x: $T) -> $Self {
$Self(x) $Self(x)
@ -99,7 +106,7 @@ pub struct Range<I> {
len: I, len: I,
} }
impl<T: Int, I: fmt::Show + RangeIndex<T>> fmt::Show for Range<I> { impl<I: RangeIndex> fmt::Show for Range<I> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f.buf, "[{} .. {})", self.begin(), self.end()) write!(f.buf, "[{} .. {})", self.begin(), self.end())
} }
@ -110,16 +117,14 @@ pub struct EachIndex<T, I> {
it: iter::Range<T>, it: iter::Range<T>,
} }
pub fn each_index<T: Int, I: RangeIndex<T>>(start: I, stop: I) -> EachIndex<T, I> { pub fn each_index<T: Int, I: IntRangeIndex<T>>(start: I, stop: I) -> EachIndex<T, I> {
EachIndex { EachIndex { it: iter::range(start.get(), stop.get()) }
it: iter::range(start.get(), stop.get())
}
} }
impl<T: Int, I: RangeIndex<T>> Iterator<I> for EachIndex<T, I> { impl<T: Int, I: IntRangeIndex<T>> Iterator<I> for EachIndex<T, I> {
#[inline] #[inline]
fn next(&mut self) -> Option<I> { fn next(&mut self) -> Option<I> {
self.it.next().map(|i| RangeIndex::new(i)) self.it.next().map(|i| IntRangeIndex::new(i))
} }
#[inline] #[inline]
@ -128,7 +133,7 @@ impl<T: Int, I: RangeIndex<T>> Iterator<I> for EachIndex<T, I> {
} }
} }
impl<T: Int, I: RangeIndex<T>> Range<I> { impl<I: RangeIndex> Range<I> {
#[inline] #[inline]
pub fn new(off: I, len: I) -> Range<I> { pub fn new(off: I, len: I) -> Range<I> {
Range { off: off, len: len } Range { off: off, len: len }
@ -146,39 +151,11 @@ impl<T: Int, I: RangeIndex<T>> Range<I> {
#[inline] #[inline]
pub fn end(&self) -> I { self.off + self.len } pub fn end(&self) -> I { self.off + self.len }
#[inline]
pub fn each_index(&self) -> EachIndex<T, I> {
each_index(self.off, self.off + self.len)
}
#[inline] #[inline]
pub fn contains(&self, i: I) -> bool { pub fn contains(&self, i: I) -> bool {
i >= self.begin() && i < self.end() i >= self.begin() && i < self.end()
} }
#[inline]
pub fn is_valid_for_string(&self, s: &str) -> bool {
let s_len = s.len();
match num::cast::<uint, T>(s_len) {
Some(len) => {
let len = RangeIndex::new(len);
self.begin() < len
&& self.end() <= len
&& self.length() <= len
},
None => {
debug!("Range<T>::is_valid_for_string: string length (len={}) is longer than the \
max value for the range index (max={})", s_len,
{
let max: T = Bounded::max_value();
let val: I = RangeIndex::new(max);
val
});
false
},
}
}
#[inline] #[inline]
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.len.is_zero() self.len.is_zero()
@ -254,6 +231,37 @@ impl<T: Int, I: RangeIndex<T>> Range<I> {
fail!("relation_to_range(): didn't classify self={}, other={}", fail!("relation_to_range(): didn't classify self={}, other={}",
self, other); self, other);
} }
}
/// Methods for `Range`s with indices based on integer values
impl<T: Int, I: IntRangeIndex<T>> Range<I> {
#[inline]
pub fn each_index(&self) -> EachIndex<T, I> {
each_index(self.off, self.off + self.len)
}
#[inline]
pub fn is_valid_for_string(&self, s: &str) -> bool {
let s_len = s.len();
match num::cast::<uint, T>(s_len) {
Some(len) => {
let len = IntRangeIndex::new(len);
self.begin() < len
&& self.end() <= len
&& self.length() <= len
},
None => {
debug!("Range<T>::is_valid_for_string: string length (len={}) is longer than the \
max value for the range index (max={})", s_len,
{
let max: T = Bounded::max_value();
let val: I = IntRangeIndex::new(max);
val
});
false
},
}
}
#[inline] #[inline]
pub fn repair_after_coalesced_range(&mut self, other: &Range<I>) { pub fn repair_after_coalesced_range(&mut self, other: &Range<I>) {
@ -261,7 +269,7 @@ impl<T: Int, I: RangeIndex<T>> Range<I> {
debug!("repair_after_coalesced_range: possibly repairing range {}", *self); debug!("repair_after_coalesced_range: possibly repairing range {}", *self);
debug!("repair_after_coalesced_range: relation of original range and coalesced range {}: {}", debug!("repair_after_coalesced_range: relation of original range and coalesced range {}: {}",
*other, relation); *other, relation);
let _1: I = RangeIndex::new(num::one::<T>()); let _1: I = IntRangeIndex::new(num::one::<T>());
match relation { match relation {
EntirelyBefore => {}, EntirelyBefore => {},
EntirelyAfter => { self.shift_by(-other.length()); }, EntirelyAfter => { self.shift_by(-other.length()); },