2
2
crate :: TextSize ,
3
3
std:: {
4
4
cmp,
5
- convert:: { TryFrom , TryInto } ,
5
+ convert:: TryInto ,
6
6
fmt,
7
- ops:: { Bound , Index , IndexMut , Range , RangeBounds } ,
7
+ ops:: { Bound , Index , IndexMut , RangeBounds } ,
8
8
} ,
9
9
} ;
10
10
@@ -30,21 +30,28 @@ use {
30
30
/// † See the note on [`TextRange::len`] for differing behavior for incorrect reverse ranges.
31
31
#[ derive( Copy , Clone , Eq , PartialEq , Hash ) ]
32
32
pub struct TextRange {
33
+ // Invariant: start <= end
33
34
start : TextSize ,
34
35
end : TextSize ,
35
36
}
36
37
37
- #[ allow( non_snake_case) ]
38
- pub ( crate ) const fn TextRange ( start : TextSize , end : TextSize ) -> TextRange {
39
- TextRange { start, end }
40
- }
41
-
42
38
impl fmt:: Debug for TextRange {
43
39
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
44
40
write ! ( f, "[{}..{})" , self . start( ) , self . end( ) )
45
41
}
46
42
}
47
43
44
+ /// Creates a new `TextRange` with given `start` and `end.
45
+ ///
46
+ /// # Panics
47
+ ///
48
+ /// Panics if `end < start`.
49
+ #[ allow( non_snake_case) ]
50
+ pub fn TextRange ( start : TextSize , end : TextSize ) -> TextRange {
51
+ assert ! ( start <= end) ;
52
+ TextRange { start, end }
53
+ }
54
+
48
55
/// Identity methods.
49
56
impl TextRange {
50
57
/// The start point of this range.
@@ -58,11 +65,6 @@ impl TextRange {
58
65
}
59
66
60
67
/// The size of this range.
61
- ///
62
- /// # Panics
63
- ///
64
- /// When `end() < start()`, triggers a subtraction overflow.
65
- /// This will panic with debug assertions, and overflow without.
66
68
pub const fn len ( self ) -> TextSize {
67
69
// HACK for const fn: math on primitives only
68
70
TextSize ( self . end ( ) . raw - self . start ( ) . raw )
@@ -71,11 +73,10 @@ impl TextRange {
71
73
/// Check if this range empty or reversed.
72
74
///
73
75
/// When `end() < start()`, this returns false.
74
- /// Code should prefer `is_empty()` to `len() == 0`,
75
- /// as this safeguards against incorrect reverse ranges.
76
+ /// Code should prefer `is_empty()` to `len() == 0`.
76
77
pub const fn is_empty ( self ) -> bool {
77
78
// HACK for const fn: math on primitives only
78
- self . start ( ) . raw > = self . end ( ) . raw
79
+ self . start ( ) . raw = = self . end ( ) . raw
79
80
}
80
81
}
81
82
@@ -91,7 +92,10 @@ impl TextRange {
91
92
pub fn intersection ( lhs : TextRange , rhs : TextRange ) -> Option < TextRange > {
92
93
let start = cmp:: max ( lhs. start ( ) , rhs. start ( ) ) ;
93
94
let end = cmp:: min ( lhs. end ( ) , rhs. end ( ) ) ;
94
- Some ( TextRange ( start, end) ) . filter ( |_| start <= end)
95
+ if end < start {
96
+ return None ;
97
+ }
98
+ Some ( TextRange ( start, end) )
95
99
}
96
100
97
101
/// The smallest range that completely contains both ranges.
@@ -145,54 +149,3 @@ impl RangeBounds<TextSize> for TextRange {
145
149
Bound :: Excluded ( & self . end )
146
150
}
147
151
}
148
-
149
- macro_rules! conversions {
150
- ( From <$lte: ident> for TextRange ) => {
151
- impl From <Range <$lte>> for TextRange {
152
- fn from( value: Range <$lte>) -> TextRange {
153
- TextRange ( value. start. into( ) , value. end. into( ) )
154
- }
155
- }
156
- // Just support `start..end` for now, not `..end`, `start..=end`, `..=end`.
157
- } ;
158
- ( TryFrom <$gt: ident> for TextRange ) => {
159
- impl TryFrom <Range <$gt>> for TextRange {
160
- type Error = <$gt as TryInto <u32 >>:: Error ;
161
- fn try_from( value: Range <$gt>) -> Result <TextRange , Self :: Error > {
162
- Ok ( TextRange ( value. start. try_into( ) ?, value. end. try_into( ) ?) )
163
- }
164
- }
165
- // Just support `start..end` for now, not `..end`, `start..=end`, `..=end`.
166
- } ;
167
- {
168
- lt TextSize [ $( $lt: ident) * ]
169
- eq TextSize [ $( $eq: ident) * ]
170
- gt TextSize [ $( $gt: ident) * ]
171
- varries [ $( $var: ident) * ]
172
- } => {
173
- $(
174
- conversions!( From <$lt> for TextRange ) ;
175
- // unlike TextSize, we do not provide conversions in the "out" direction.
176
- ) *
177
-
178
- $(
179
- conversions!( From <$eq> for TextRange ) ;
180
- ) *
181
-
182
- $(
183
- conversions!( TryFrom <$gt> for TextRange ) ;
184
- ) *
185
-
186
- $(
187
- conversions!( TryFrom <$var> for TextRange ) ;
188
- ) *
189
- } ;
190
- }
191
-
192
- // FIXME: when `default impl` is usable, change to blanket impls for [Try]Into<TextSize> instead
193
- conversions ! {
194
- lt TextSize [ u8 u16 ]
195
- eq TextSize [ u32 TextSize ]
196
- gt TextSize [ u64 ]
197
- varries [ usize ]
198
- }
0 commit comments