summaryrefslogtreecommitdiffstats
path: root/vendor/text-size/src/range.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/text-size/src/range.rs')
-rw-r--r--vendor/text-size/src/range.rs912
1 files changed, 456 insertions, 456 deletions
diff --git a/vendor/text-size/src/range.rs b/vendor/text-size/src/range.rs
index 4a98deec5..ab3c50d07 100644
--- a/vendor/text-size/src/range.rs
+++ b/vendor/text-size/src/range.rs
@@ -1,456 +1,456 @@
-use cmp::Ordering;
-
-use {
- crate::TextSize,
- std::{
- cmp, fmt,
- ops::{Add, AddAssign, Bound, Index, IndexMut, Range, RangeBounds, Sub, SubAssign},
- },
-};
-
-/// A range in text, represented as a pair of [`TextSize`][struct@TextSize].
-///
-/// It is a logic error for `start` to be greater than `end`.
-#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
-pub struct TextRange {
- // Invariant: start <= end
- start: TextSize,
- end: TextSize,
-}
-
-impl fmt::Debug for TextRange {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}..{}", self.start().raw, self.end().raw)
- }
-}
-
-impl TextRange {
- /// Creates a new `TextRange` with the given `start` and `end` (`start..end`).
- ///
- /// # Panics
- ///
- /// Panics if `end < start`.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use text_size::*;
- /// let start = TextSize::from(5);
- /// let end = TextSize::from(10);
- /// let range = TextRange::new(start, end);
- ///
- /// assert_eq!(range.start(), start);
- /// assert_eq!(range.end(), end);
- /// assert_eq!(range.len(), end - start);
- /// ```
- #[inline]
- pub fn new(start: TextSize, end: TextSize) -> TextRange {
- assert!(start <= end);
- TextRange { start, end }
- }
-
- /// Create a new `TextRange` with the given `offset` and `len` (`offset..offset + len`).
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use text_size::*;
- /// let text = "0123456789";
- ///
- /// let offset = TextSize::from(2);
- /// let length = TextSize::from(5);
- /// let range = TextRange::at(offset, length);
- ///
- /// assert_eq!(range, TextRange::new(offset, offset + length));
- /// assert_eq!(&text[range], "23456")
- /// ```
- #[inline]
- pub fn at(offset: TextSize, len: TextSize) -> TextRange {
- TextRange::new(offset, offset + len)
- }
-
- /// Create a zero-length range at the specified offset (`offset..offset`).
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use text_size::*;
- /// let point: TextSize;
- /// # point = TextSize::from(3);
- /// let range = TextRange::empty(point);
- /// assert!(range.is_empty());
- /// assert_eq!(range, TextRange::new(point, point));
- /// ```
- #[inline]
- pub fn empty(offset: TextSize) -> TextRange {
- TextRange {
- start: offset,
- end: offset,
- }
- }
-
- /// Create a range up to the given end (`..end`).
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use text_size::*;
- /// let point: TextSize;
- /// # point = TextSize::from(12);
- /// let range = TextRange::up_to(point);
- ///
- /// assert_eq!(range.len(), point);
- /// assert_eq!(range, TextRange::new(0.into(), point));
- /// assert_eq!(range, TextRange::at(0.into(), point));
- /// ```
- #[inline]
- pub fn up_to(end: TextSize) -> TextRange {
- TextRange {
- start: 0.into(),
- end,
- }
- }
-}
-
-/// Identity methods.
-impl TextRange {
- /// The start point of this range.
- #[inline]
- pub const fn start(self) -> TextSize {
- self.start
- }
-
- /// The end point of this range.
- #[inline]
- pub const fn end(self) -> TextSize {
- self.end
- }
-
- /// The size of this range.
- #[inline]
- pub const fn len(self) -> TextSize {
- // HACK for const fn: math on primitives only
- TextSize {
- raw: self.end().raw - self.start().raw,
- }
- }
-
- /// Check if this range is empty.
- #[inline]
- pub const fn is_empty(self) -> bool {
- // HACK for const fn: math on primitives only
- self.start().raw == self.end().raw
- }
-}
-
-/// Manipulation methods.
-impl TextRange {
- /// Check if this range contains an offset.
- ///
- /// The end index is considered excluded.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use text_size::*;
- /// let (start, end): (TextSize, TextSize);
- /// # start = 10.into(); end = 20.into();
- /// let range = TextRange::new(start, end);
- /// assert!(range.contains(start));
- /// assert!(!range.contains(end));
- /// ```
- #[inline]
- pub fn contains(self, offset: TextSize) -> bool {
- self.start() <= offset && offset < self.end()
- }
-
- /// Check if this range contains an offset.
- ///
- /// The end index is considered included.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use text_size::*;
- /// let (start, end): (TextSize, TextSize);
- /// # start = 10.into(); end = 20.into();
- /// let range = TextRange::new(start, end);
- /// assert!(range.contains_inclusive(start));
- /// assert!(range.contains_inclusive(end));
- /// ```
- #[inline]
- pub fn contains_inclusive(self, offset: TextSize) -> bool {
- self.start() <= offset && offset <= self.end()
- }
-
- /// Check if this range completely contains another range.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use text_size::*;
- /// let larger = TextRange::new(0.into(), 20.into());
- /// let smaller = TextRange::new(5.into(), 15.into());
- /// assert!(larger.contains_range(smaller));
- /// assert!(!smaller.contains_range(larger));
- ///
- /// // a range always contains itself
- /// assert!(larger.contains_range(larger));
- /// assert!(smaller.contains_range(smaller));
- /// ```
- #[inline]
- pub fn contains_range(self, other: TextRange) -> bool {
- self.start() <= other.start() && other.end() <= self.end()
- }
-
- /// The range covered by both ranges, if it exists.
- /// If the ranges touch but do not overlap, the output range is empty.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use text_size::*;
- /// assert_eq!(
- /// TextRange::intersect(
- /// TextRange::new(0.into(), 10.into()),
- /// TextRange::new(5.into(), 15.into()),
- /// ),
- /// Some(TextRange::new(5.into(), 10.into())),
- /// );
- /// ```
- #[inline]
- pub fn intersect(self, other: TextRange) -> Option<TextRange> {
- let start = cmp::max(self.start(), other.start());
- let end = cmp::min(self.end(), other.end());
- if end < start {
- return None;
- }
- Some(TextRange::new(start, end))
- }
-
- /// Extends the range to cover `other` as well.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use text_size::*;
- /// assert_eq!(
- /// TextRange::cover(
- /// TextRange::new(0.into(), 5.into()),
- /// TextRange::new(15.into(), 20.into()),
- /// ),
- /// TextRange::new(0.into(), 20.into()),
- /// );
- /// ```
- #[inline]
- pub fn cover(self, other: TextRange) -> TextRange {
- let start = cmp::min(self.start(), other.start());
- let end = cmp::max(self.end(), other.end());
- TextRange::new(start, end)
- }
-
- /// Extends the range to cover `other` offsets as well.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use text_size::*;
- /// assert_eq!(
- /// TextRange::empty(0.into()).cover_offset(20.into()),
- /// TextRange::new(0.into(), 20.into()),
- /// )
- /// ```
- #[inline]
- pub fn cover_offset(self, offset: TextSize) -> TextRange {
- self.cover(TextRange::empty(offset))
- }
-
- /// Add an offset to this range.
- ///
- /// Note that this is not appropriate for changing where a `TextRange` is
- /// within some string; rather, it is for changing the reference anchor
- /// that the `TextRange` is measured against.
- ///
- /// The unchecked version (`Add::add`) will _always_ panic on overflow,
- /// in contrast to primitive integers, which check in debug mode only.
- #[inline]
- pub fn checked_add(self, offset: TextSize) -> Option<TextRange> {
- Some(TextRange {
- start: self.start.checked_add(offset)?,
- end: self.end.checked_add(offset)?,
- })
- }
-
- /// Subtract an offset from this range.
- ///
- /// Note that this is not appropriate for changing where a `TextRange` is
- /// within some string; rather, it is for changing the reference anchor
- /// that the `TextRange` is measured against.
- ///
- /// The unchecked version (`Sub::sub`) will _always_ panic on overflow,
- /// in contrast to primitive integers, which check in debug mode only.
- #[inline]
- pub fn checked_sub(self, offset: TextSize) -> Option<TextRange> {
- Some(TextRange {
- start: self.start.checked_sub(offset)?,
- end: self.end.checked_sub(offset)?,
- })
- }
-
- /// Relative order of the two ranges (overlapping ranges are considered
- /// equal).
- ///
- ///
- /// This is useful when, for example, binary searching an array of disjoint
- /// ranges.
- ///
- /// # Examples
- ///
- /// ```
- /// # use text_size::*;
- /// # use std::cmp::Ordering;
- ///
- /// let a = TextRange::new(0.into(), 3.into());
- /// let b = TextRange::new(4.into(), 5.into());
- /// assert_eq!(a.ordering(b), Ordering::Less);
- ///
- /// let a = TextRange::new(0.into(), 3.into());
- /// let b = TextRange::new(3.into(), 5.into());
- /// assert_eq!(a.ordering(b), Ordering::Less);
- ///
- /// let a = TextRange::new(0.into(), 3.into());
- /// let b = TextRange::new(2.into(), 5.into());
- /// assert_eq!(a.ordering(b), Ordering::Equal);
- ///
- /// let a = TextRange::new(0.into(), 3.into());
- /// let b = TextRange::new(2.into(), 2.into());
- /// assert_eq!(a.ordering(b), Ordering::Equal);
- ///
- /// let a = TextRange::new(2.into(), 3.into());
- /// let b = TextRange::new(2.into(), 2.into());
- /// assert_eq!(a.ordering(b), Ordering::Greater);
- /// ```
- #[inline]
- pub fn ordering(self, other: TextRange) -> Ordering {
- if self.end() <= other.start() {
- Ordering::Less
- } else if other.end() <= self.start() {
- Ordering::Greater
- } else {
- Ordering::Equal
- }
- }
-}
-
-impl Index<TextRange> for str {
- type Output = str;
- #[inline]
- fn index(&self, index: TextRange) -> &str {
- &self[Range::<usize>::from(index)]
- }
-}
-
-impl Index<TextRange> for String {
- type Output = str;
- #[inline]
- fn index(&self, index: TextRange) -> &str {
- &self[Range::<usize>::from(index)]
- }
-}
-
-impl IndexMut<TextRange> for str {
- #[inline]
- fn index_mut(&mut self, index: TextRange) -> &mut str {
- &mut self[Range::<usize>::from(index)]
- }
-}
-
-impl IndexMut<TextRange> for String {
- #[inline]
- fn index_mut(&mut self, index: TextRange) -> &mut str {
- &mut self[Range::<usize>::from(index)]
- }
-}
-
-impl RangeBounds<TextSize> for TextRange {
- fn start_bound(&self) -> Bound<&TextSize> {
- Bound::Included(&self.start)
- }
-
- fn end_bound(&self) -> Bound<&TextSize> {
- Bound::Excluded(&self.end)
- }
-}
-
-impl<T> From<TextRange> for Range<T>
-where
- T: From<TextSize>,
-{
- #[inline]
- fn from(r: TextRange) -> Self {
- r.start().into()..r.end().into()
- }
-}
-
-macro_rules! ops {
- (impl $Op:ident for TextRange by fn $f:ident = $op:tt) => {
- impl $Op<&TextSize> for TextRange {
- type Output = TextRange;
- #[inline]
- fn $f(self, other: &TextSize) -> TextRange {
- self $op *other
- }
- }
- impl<T> $Op<T> for &TextRange
- where
- TextRange: $Op<T, Output=TextRange>,
- {
- type Output = TextRange;
- #[inline]
- fn $f(self, other: T) -> TextRange {
- *self $op other
- }
- }
- };
-}
-
-impl Add<TextSize> for TextRange {
- type Output = TextRange;
- #[inline]
- fn add(self, offset: TextSize) -> TextRange {
- self.checked_add(offset)
- .expect("TextRange +offset overflowed")
- }
-}
-
-impl Sub<TextSize> for TextRange {
- type Output = TextRange;
- #[inline]
- fn sub(self, offset: TextSize) -> TextRange {
- self.checked_sub(offset)
- .expect("TextRange -offset overflowed")
- }
-}
-
-ops!(impl Add for TextRange by fn add = +);
-ops!(impl Sub for TextRange by fn sub = -);
-
-impl<A> AddAssign<A> for TextRange
-where
- TextRange: Add<A, Output = TextRange>,
-{
- #[inline]
- fn add_assign(&mut self, rhs: A) {
- *self = *self + rhs
- }
-}
-
-impl<S> SubAssign<S> for TextRange
-where
- TextRange: Sub<S, Output = TextRange>,
-{
- #[inline]
- fn sub_assign(&mut self, rhs: S) {
- *self = *self - rhs
- }
-}
+use cmp::Ordering;
+
+use {
+ crate::TextSize,
+ std::{
+ cmp, fmt,
+ ops::{Add, AddAssign, Bound, Index, IndexMut, Range, RangeBounds, Sub, SubAssign},
+ },
+};
+
+/// A range in text, represented as a pair of [`TextSize`][struct@TextSize].
+///
+/// It is a logic error for `start` to be greater than `end`.
+#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
+pub struct TextRange {
+ // Invariant: start <= end
+ start: TextSize,
+ end: TextSize,
+}
+
+impl fmt::Debug for TextRange {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}..{}", self.start().raw, self.end().raw)
+ }
+}
+
+impl TextRange {
+ /// Creates a new `TextRange` with the given `start` and `end` (`start..end`).
+ ///
+ /// # Panics
+ ///
+ /// Panics if `end < start`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use text_size::*;
+ /// let start = TextSize::from(5);
+ /// let end = TextSize::from(10);
+ /// let range = TextRange::new(start, end);
+ ///
+ /// assert_eq!(range.start(), start);
+ /// assert_eq!(range.end(), end);
+ /// assert_eq!(range.len(), end - start);
+ /// ```
+ #[inline]
+ pub const fn new(start: TextSize, end: TextSize) -> TextRange {
+ assert!(start.raw <= end.raw);
+ TextRange { start, end }
+ }
+
+ /// Create a new `TextRange` with the given `offset` and `len` (`offset..offset + len`).
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use text_size::*;
+ /// let text = "0123456789";
+ ///
+ /// let offset = TextSize::from(2);
+ /// let length = TextSize::from(5);
+ /// let range = TextRange::at(offset, length);
+ ///
+ /// assert_eq!(range, TextRange::new(offset, offset + length));
+ /// assert_eq!(&text[range], "23456")
+ /// ```
+ #[inline]
+ pub const fn at(offset: TextSize, len: TextSize) -> TextRange {
+ TextRange::new(offset, TextSize::new(offset.raw + len.raw))
+ }
+
+ /// Create a zero-length range at the specified offset (`offset..offset`).
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use text_size::*;
+ /// let point: TextSize;
+ /// # point = TextSize::from(3);
+ /// let range = TextRange::empty(point);
+ /// assert!(range.is_empty());
+ /// assert_eq!(range, TextRange::new(point, point));
+ /// ```
+ #[inline]
+ pub const fn empty(offset: TextSize) -> TextRange {
+ TextRange {
+ start: offset,
+ end: offset,
+ }
+ }
+
+ /// Create a range up to the given end (`..end`).
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use text_size::*;
+ /// let point: TextSize;
+ /// # point = TextSize::from(12);
+ /// let range = TextRange::up_to(point);
+ ///
+ /// assert_eq!(range.len(), point);
+ /// assert_eq!(range, TextRange::new(0.into(), point));
+ /// assert_eq!(range, TextRange::at(0.into(), point));
+ /// ```
+ #[inline]
+ pub const fn up_to(end: TextSize) -> TextRange {
+ TextRange {
+ start: TextSize::new(0),
+ end,
+ }
+ }
+}
+
+/// Identity methods.
+impl TextRange {
+ /// The start point of this range.
+ #[inline]
+ pub const fn start(self) -> TextSize {
+ self.start
+ }
+
+ /// The end point of this range.
+ #[inline]
+ pub const fn end(self) -> TextSize {
+ self.end
+ }
+
+ /// The size of this range.
+ #[inline]
+ pub const fn len(self) -> TextSize {
+ // HACK for const fn: math on primitives only
+ TextSize {
+ raw: self.end().raw - self.start().raw,
+ }
+ }
+
+ /// Check if this range is empty.
+ #[inline]
+ pub const fn is_empty(self) -> bool {
+ // HACK for const fn: math on primitives only
+ self.start().raw == self.end().raw
+ }
+}
+
+/// Manipulation methods.
+impl TextRange {
+ /// Check if this range contains an offset.
+ ///
+ /// The end index is considered excluded.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use text_size::*;
+ /// let (start, end): (TextSize, TextSize);
+ /// # start = 10.into(); end = 20.into();
+ /// let range = TextRange::new(start, end);
+ /// assert!(range.contains(start));
+ /// assert!(!range.contains(end));
+ /// ```
+ #[inline]
+ pub fn contains(self, offset: TextSize) -> bool {
+ self.start() <= offset && offset < self.end()
+ }
+
+ /// Check if this range contains an offset.
+ ///
+ /// The end index is considered included.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use text_size::*;
+ /// let (start, end): (TextSize, TextSize);
+ /// # start = 10.into(); end = 20.into();
+ /// let range = TextRange::new(start, end);
+ /// assert!(range.contains_inclusive(start));
+ /// assert!(range.contains_inclusive(end));
+ /// ```
+ #[inline]
+ pub fn contains_inclusive(self, offset: TextSize) -> bool {
+ self.start() <= offset && offset <= self.end()
+ }
+
+ /// Check if this range completely contains another range.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use text_size::*;
+ /// let larger = TextRange::new(0.into(), 20.into());
+ /// let smaller = TextRange::new(5.into(), 15.into());
+ /// assert!(larger.contains_range(smaller));
+ /// assert!(!smaller.contains_range(larger));
+ ///
+ /// // a range always contains itself
+ /// assert!(larger.contains_range(larger));
+ /// assert!(smaller.contains_range(smaller));
+ /// ```
+ #[inline]
+ pub fn contains_range(self, other: TextRange) -> bool {
+ self.start() <= other.start() && other.end() <= self.end()
+ }
+
+ /// The range covered by both ranges, if it exists.
+ /// If the ranges touch but do not overlap, the output range is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use text_size::*;
+ /// assert_eq!(
+ /// TextRange::intersect(
+ /// TextRange::new(0.into(), 10.into()),
+ /// TextRange::new(5.into(), 15.into()),
+ /// ),
+ /// Some(TextRange::new(5.into(), 10.into())),
+ /// );
+ /// ```
+ #[inline]
+ pub fn intersect(self, other: TextRange) -> Option<TextRange> {
+ let start = cmp::max(self.start(), other.start());
+ let end = cmp::min(self.end(), other.end());
+ if end < start {
+ return None;
+ }
+ Some(TextRange::new(start, end))
+ }
+
+ /// Extends the range to cover `other` as well.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use text_size::*;
+ /// assert_eq!(
+ /// TextRange::cover(
+ /// TextRange::new(0.into(), 5.into()),
+ /// TextRange::new(15.into(), 20.into()),
+ /// ),
+ /// TextRange::new(0.into(), 20.into()),
+ /// );
+ /// ```
+ #[inline]
+ pub fn cover(self, other: TextRange) -> TextRange {
+ let start = cmp::min(self.start(), other.start());
+ let end = cmp::max(self.end(), other.end());
+ TextRange::new(start, end)
+ }
+
+ /// Extends the range to cover `other` offsets as well.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use text_size::*;
+ /// assert_eq!(
+ /// TextRange::empty(0.into()).cover_offset(20.into()),
+ /// TextRange::new(0.into(), 20.into()),
+ /// )
+ /// ```
+ #[inline]
+ pub fn cover_offset(self, offset: TextSize) -> TextRange {
+ self.cover(TextRange::empty(offset))
+ }
+
+ /// Add an offset to this range.
+ ///
+ /// Note that this is not appropriate for changing where a `TextRange` is
+ /// within some string; rather, it is for changing the reference anchor
+ /// that the `TextRange` is measured against.
+ ///
+ /// The unchecked version (`Add::add`) will _always_ panic on overflow,
+ /// in contrast to primitive integers, which check in debug mode only.
+ #[inline]
+ pub fn checked_add(self, offset: TextSize) -> Option<TextRange> {
+ Some(TextRange {
+ start: self.start.checked_add(offset)?,
+ end: self.end.checked_add(offset)?,
+ })
+ }
+
+ /// Subtract an offset from this range.
+ ///
+ /// Note that this is not appropriate for changing where a `TextRange` is
+ /// within some string; rather, it is for changing the reference anchor
+ /// that the `TextRange` is measured against.
+ ///
+ /// The unchecked version (`Sub::sub`) will _always_ panic on overflow,
+ /// in contrast to primitive integers, which check in debug mode only.
+ #[inline]
+ pub fn checked_sub(self, offset: TextSize) -> Option<TextRange> {
+ Some(TextRange {
+ start: self.start.checked_sub(offset)?,
+ end: self.end.checked_sub(offset)?,
+ })
+ }
+
+ /// Relative order of the two ranges (overlapping ranges are considered
+ /// equal).
+ ///
+ ///
+ /// This is useful when, for example, binary searching an array of disjoint
+ /// ranges.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use text_size::*;
+ /// # use std::cmp::Ordering;
+ ///
+ /// let a = TextRange::new(0.into(), 3.into());
+ /// let b = TextRange::new(4.into(), 5.into());
+ /// assert_eq!(a.ordering(b), Ordering::Less);
+ ///
+ /// let a = TextRange::new(0.into(), 3.into());
+ /// let b = TextRange::new(3.into(), 5.into());
+ /// assert_eq!(a.ordering(b), Ordering::Less);
+ ///
+ /// let a = TextRange::new(0.into(), 3.into());
+ /// let b = TextRange::new(2.into(), 5.into());
+ /// assert_eq!(a.ordering(b), Ordering::Equal);
+ ///
+ /// let a = TextRange::new(0.into(), 3.into());
+ /// let b = TextRange::new(2.into(), 2.into());
+ /// assert_eq!(a.ordering(b), Ordering::Equal);
+ ///
+ /// let a = TextRange::new(2.into(), 3.into());
+ /// let b = TextRange::new(2.into(), 2.into());
+ /// assert_eq!(a.ordering(b), Ordering::Greater);
+ /// ```
+ #[inline]
+ pub fn ordering(self, other: TextRange) -> Ordering {
+ if self.end() <= other.start() {
+ Ordering::Less
+ } else if other.end() <= self.start() {
+ Ordering::Greater
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+impl Index<TextRange> for str {
+ type Output = str;
+ #[inline]
+ fn index(&self, index: TextRange) -> &str {
+ &self[Range::<usize>::from(index)]
+ }
+}
+
+impl Index<TextRange> for String {
+ type Output = str;
+ #[inline]
+ fn index(&self, index: TextRange) -> &str {
+ &self[Range::<usize>::from(index)]
+ }
+}
+
+impl IndexMut<TextRange> for str {
+ #[inline]
+ fn index_mut(&mut self, index: TextRange) -> &mut str {
+ &mut self[Range::<usize>::from(index)]
+ }
+}
+
+impl IndexMut<TextRange> for String {
+ #[inline]
+ fn index_mut(&mut self, index: TextRange) -> &mut str {
+ &mut self[Range::<usize>::from(index)]
+ }
+}
+
+impl RangeBounds<TextSize> for TextRange {
+ fn start_bound(&self) -> Bound<&TextSize> {
+ Bound::Included(&self.start)
+ }
+
+ fn end_bound(&self) -> Bound<&TextSize> {
+ Bound::Excluded(&self.end)
+ }
+}
+
+impl<T> From<TextRange> for Range<T>
+where
+ T: From<TextSize>,
+{
+ #[inline]
+ fn from(r: TextRange) -> Self {
+ r.start().into()..r.end().into()
+ }
+}
+
+macro_rules! ops {
+ (impl $Op:ident for TextRange by fn $f:ident = $op:tt) => {
+ impl $Op<&TextSize> for TextRange {
+ type Output = TextRange;
+ #[inline]
+ fn $f(self, other: &TextSize) -> TextRange {
+ self $op *other
+ }
+ }
+ impl<T> $Op<T> for &TextRange
+ where
+ TextRange: $Op<T, Output=TextRange>,
+ {
+ type Output = TextRange;
+ #[inline]
+ fn $f(self, other: T) -> TextRange {
+ *self $op other
+ }
+ }
+ };
+}
+
+impl Add<TextSize> for TextRange {
+ type Output = TextRange;
+ #[inline]
+ fn add(self, offset: TextSize) -> TextRange {
+ self.checked_add(offset)
+ .expect("TextRange +offset overflowed")
+ }
+}
+
+impl Sub<TextSize> for TextRange {
+ type Output = TextRange;
+ #[inline]
+ fn sub(self, offset: TextSize) -> TextRange {
+ self.checked_sub(offset)
+ .expect("TextRange -offset overflowed")
+ }
+}
+
+ops!(impl Add for TextRange by fn add = +);
+ops!(impl Sub for TextRange by fn sub = -);
+
+impl<A> AddAssign<A> for TextRange
+where
+ TextRange: Add<A, Output = TextRange>,
+{
+ #[inline]
+ fn add_assign(&mut self, rhs: A) {
+ *self = *self + rhs
+ }
+}
+
+impl<S> SubAssign<S> for TextRange
+where
+ TextRange: Sub<S, Output = TextRange>,
+{
+ #[inline]
+ fn sub_assign(&mut self, rhs: S) {
+ *self = *self - rhs
+ }
+}