Skip to content

Commit af39466

Browse files
committed
Add ops for TextRange
1 parent 4b68ff2 commit af39466

File tree

1 file changed

+96
-1
lines changed

1 file changed

+96
-1
lines changed

src/range.rs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use {
22
crate::TextSize,
33
std::{
44
cmp, fmt,
5-
ops::{Bound, Index, IndexMut, Range, RangeBounds},
5+
ops::{Add, AddAssign, Bound, Index, IndexMut, Range, RangeBounds, Sub, SubAssign},
66
},
77
};
88

@@ -133,6 +133,38 @@ impl TextRange {
133133
let end = cmp::max(lhs.end(), rhs.end());
134134
TextRange(start, end)
135135
}
136+
137+
/// Add an offset to this range.
138+
///
139+
/// Note that this is not appropriate for changing where a `TextRange` is
140+
/// within some string; rather, it is for changing the reference anchor
141+
/// that the `TextRange` is measured against.
142+
///
143+
/// The unchecked version (`Add::add`) will _always_ panic on overflow,
144+
/// in contrast to primitive integers, which check in debug mode only.
145+
#[inline]
146+
pub fn checked_add(self, offset: TextSize) -> Option<TextRange> {
147+
Some(TextRange {
148+
start: self.start.checked_add(offset)?,
149+
end: self.end.checked_add(offset)?,
150+
})
151+
}
152+
153+
/// Subtract an offset from this range.
154+
///
155+
/// Note that this is not appropriate for changing where a `TextRange` is
156+
/// within some string; rather, it is for changing the reference anchor
157+
/// that the `TextRange` is measured against.
158+
///
159+
/// The unchecked version (`Sub::sub`) will _always_ panic on overflow,
160+
/// in contrast to primitive integers, which check in debug mode only.
161+
#[inline]
162+
pub fn checked_sub(self, offset: TextSize) -> Option<TextRange> {
163+
Some(TextRange {
164+
start: self.start.checked_sub(offset)?,
165+
end: self.end.checked_sub(offset)?,
166+
})
167+
}
136168
}
137169

138170
impl Index<TextRange> for str {
@@ -169,3 +201,66 @@ where
169201
r.start().into()..r.end().into()
170202
}
171203
}
204+
205+
macro_rules! ops {
206+
(impl $Op:ident for TextRange by fn $f:ident = $op:tt) => {
207+
impl $Op<&TextSize> for TextRange {
208+
type Output = TextRange;
209+
#[inline]
210+
fn $f(self, other: &TextSize) -> TextRange {
211+
self $op *other
212+
}
213+
}
214+
impl<T> $Op<T> for &TextRange
215+
where
216+
TextRange: $Op<T, Output=TextRange>,
217+
{
218+
type Output = TextRange;
219+
#[inline]
220+
fn $f(self, other: T) -> TextRange {
221+
*self $op other
222+
}
223+
}
224+
};
225+
}
226+
227+
impl Add<TextSize> for TextRange {
228+
type Output = TextRange;
229+
#[inline]
230+
fn add(self, offset: TextSize) -> TextRange {
231+
self.checked_add(offset)
232+
.expect("TextRange +offset overflowed")
233+
}
234+
}
235+
236+
impl Sub<TextSize> for TextRange {
237+
type Output = TextRange;
238+
#[inline]
239+
fn sub(self, offset: TextSize) -> TextRange {
240+
self.checked_sub(offset)
241+
.expect("TextRange -offset overflowed")
242+
}
243+
}
244+
245+
ops!(impl Add for TextRange by fn add = +);
246+
ops!(impl Sub for TextRange by fn sub = -);
247+
248+
impl<A> AddAssign<A> for TextRange
249+
where
250+
TextRange: Add<A, Output = TextRange>,
251+
{
252+
#[inline]
253+
fn add_assign(&mut self, rhs: A) {
254+
*self = *self + rhs
255+
}
256+
}
257+
258+
impl<S> SubAssign<S> for TextRange
259+
where
260+
TextRange: Sub<S, Output = TextRange>,
261+
{
262+
#[inline]
263+
fn sub_assign(&mut self, rhs: S) {
264+
*self = *self - rhs
265+
}
266+
}

0 commit comments

Comments
 (0)