1
1
#[ cfg( feature = "serde" ) ]
2
2
extern crate serde;
3
3
4
- use std:: { fmt, ops, iter} ;
5
-
4
+ use std:: { fmt, iter, ops} ;
6
5
7
6
/// An offset into text.
8
7
/// Offset is represented as `u32` storing number of utf8-bytes,
@@ -37,7 +36,8 @@ impl TextUnit {
37
36
38
37
#[ inline( always) ]
39
38
pub fn from_usize ( size : usize ) -> TextUnit {
40
- #[ cfg( debug_assertions) ] {
39
+ #[ cfg( debug_assertions) ]
40
+ {
41
41
if size > u32:: max_value ( ) as usize {
42
42
panic ! ( "overflow when converting to TextUnit: {}" , size)
43
43
}
@@ -198,13 +198,13 @@ range_ops_impls!(Add, add, +, AddAssign, add_assign);
198
198
range_ops_impls ! ( Sub , sub, -, SubAssign , sub_assign) ;
199
199
200
200
impl < ' a > iter:: Sum < & ' a TextUnit > for TextUnit {
201
- fn sum < I : Iterator < Item = & ' a TextUnit > > ( iter : I ) -> TextUnit {
201
+ fn sum < I : Iterator < Item = & ' a TextUnit > > ( iter : I ) -> TextUnit {
202
202
iter. fold ( TextUnit :: from ( 0 ) , ops:: Add :: add)
203
203
}
204
204
}
205
205
206
206
impl iter:: Sum < TextUnit > for TextUnit {
207
- fn sum < I : Iterator < Item = TextUnit > > ( iter : I ) -> TextUnit {
207
+ fn sum < I : Iterator < Item = TextUnit > > ( iter : I ) -> TextUnit {
208
208
iter. fold ( TextUnit :: from ( 0 ) , ops:: Add :: add)
209
209
}
210
210
}
@@ -223,10 +223,7 @@ pub struct TextRange {
223
223
impl TextRange {
224
224
#[ inline( always) ]
225
225
pub fn checked_sub ( self , other : TextUnit ) -> Option < TextRange > {
226
- let res = TextRange :: offset_len (
227
- self . start ( ) . checked_sub ( other) ?,
228
- self . len ( )
229
- ) ;
226
+ let res = TextRange :: offset_len ( self . start ( ) . checked_sub ( other) ?, self . len ( ) ) ;
230
227
Some ( res)
231
228
}
232
229
}
@@ -287,8 +284,28 @@ impl TextRange {
287
284
288
285
#[ inline( always) ]
289
286
pub fn is_subrange ( & self , other : & TextRange ) -> bool {
290
- other. start ( ) <= self . start ( )
291
- && self . end ( ) <= other. end ( )
287
+ other. start ( ) <= self . start ( ) && self . end ( ) <= other. end ( )
288
+ }
289
+
290
+ #[ inline( always) ]
291
+ pub fn intersection ( & self , other : & TextRange ) -> Option < TextRange > {
292
+ let start = self . start . max ( other. start ( ) ) ;
293
+ let end = self . end . min ( other. end ( ) ) ;
294
+ if start <= end {
295
+ Some ( TextRange :: from_to ( start, end) )
296
+ } else {
297
+ None
298
+ }
299
+ }
300
+
301
+ #[ inline( always) ]
302
+ pub fn contains ( & self , offset : TextUnit ) -> bool {
303
+ self . start ( ) <= offset && offset < self . end ( )
304
+ }
305
+
306
+ #[ inline( always) ]
307
+ pub fn contains_inclusive ( & self , offset : TextUnit ) -> bool {
308
+ self . start ( ) <= offset && offset <= self . end ( )
292
309
}
293
310
}
294
311
@@ -310,8 +327,8 @@ impl ops::Index<TextRange> for String {
310
327
311
328
#[ cfg( feature = "serde" ) ]
312
329
mod serde_impls {
313
- use serde:: { Serialize , Serializer , Deserialize , Deserializer } ;
314
- use { TextUnit , TextRange } ;
330
+ use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
331
+ use { TextRange , TextUnit } ;
315
332
316
333
impl Serialize for TextUnit {
317
334
fn serialize < S : Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
@@ -344,6 +361,10 @@ mod serde_impls {
344
361
mod tests {
345
362
use super :: * ;
346
363
364
+ fn r ( from : u32 , to : u32 ) -> TextRange {
365
+ TextRange :: from_to ( from. into ( ) , to. into ( ) )
366
+ }
367
+
347
368
#[ test]
348
369
fn test_sum ( ) {
349
370
let xs: Vec < TextUnit > = vec ! [ 0 . into( ) , 1 . into( ) , 2 . into( ) ] ;
@@ -353,16 +374,10 @@ mod tests {
353
374
354
375
#[ test]
355
376
fn test_ops ( ) {
356
- let r = TextRange :: from_to ( 10 . into ( ) , 20 . into ( ) ) ;
377
+ let range = r ( 10 , 20 ) ;
357
378
let u: TextUnit = 5 . into ( ) ;
358
- assert_eq ! (
359
- r + u,
360
- TextRange :: from_to( 15 . into( ) , 25 . into( ) ) ,
361
- ) ;
362
- assert_eq ! (
363
- r - u,
364
- TextRange :: from_to( 5 . into( ) , 15 . into( ) ) ,
365
- ) ;
379
+ assert_eq ! ( range + u, r( 15 , 25 ) ) ;
380
+ assert_eq ! ( range - u, r( 5 , 15 ) ) ;
366
381
}
367
382
368
383
#[ test]
@@ -371,17 +386,38 @@ mod tests {
371
386
assert_eq ! ( x. checked_sub( 1 . into( ) ) , Some ( 0 . into( ) ) ) ;
372
387
assert_eq ! ( x. checked_sub( 2 . into( ) ) , None ) ;
373
388
374
- let r = TextRange :: from_to ( 1 . into ( ) , 2 . into ( ) ) ;
375
- assert_eq ! ( r. checked_sub( 1 . into( ) ) , Some ( TextRange :: from_to( 0 . into( ) , 1 . into( ) ) ) ) ;
389
+ assert_eq ! ( r( 1 , 2 ) . checked_sub( 1 . into( ) ) , Some ( r( 0 , 1 ) ) ) ;
376
390
assert_eq ! ( x. checked_sub( 2 . into( ) ) , None ) ;
377
391
}
378
392
379
393
#[ test]
380
394
fn test_subrange ( ) {
381
- let r1 = TextRange :: from_to ( 2 . into ( ) , 4 . into ( ) ) ;
382
- let r2 = TextRange :: from_to ( 2 . into ( ) , 3 . into ( ) ) ;
383
- let r3 = TextRange :: from_to ( 1 . into ( ) , 3 . into ( ) ) ;
395
+ let r1 = r ( 2 , 4 ) ;
396
+ let r2 = r ( 2 , 3 ) ;
397
+ let r3 = r ( 1 , 3 ) ;
384
398
assert ! ( r2. is_subrange( & r1) ) ;
385
399
assert ! ( !r3. is_subrange( & r1) ) ;
386
400
}
401
+
402
+ #[ test]
403
+ fn check_intersection ( ) {
404
+ assert_eq ! ( r( 1 , 2 ) . intersection( & r( 2 , 3 ) ) , Some ( r( 2 , 2 ) ) ) ;
405
+ assert_eq ! ( r( 1 , 5 ) . intersection( & r( 2 , 3 ) ) , Some ( r( 2 , 3 ) ) ) ;
406
+ assert_eq ! ( r( 1 , 2 ) . intersection( & r( 3 , 4 ) ) , None ) ;
407
+ }
408
+
409
+ #[ test]
410
+ fn check_contains ( ) {
411
+ assert ! ( !r( 1 , 3 ) . contains( 0 . into( ) ) ) ;
412
+ assert ! ( r( 1 , 3 ) . contains( 1 . into( ) ) ) ;
413
+ assert ! ( r( 1 , 3 ) . contains( 2 . into( ) ) ) ;
414
+ assert ! ( !r( 1 , 3 ) . contains( 3 . into( ) ) ) ;
415
+ assert ! ( !r( 1 , 3 ) . contains( 4 . into( ) ) ) ;
416
+
417
+ assert ! ( !r( 1 , 3 ) . contains_inclusive( 0 . into( ) ) ) ;
418
+ assert ! ( r( 1 , 3 ) . contains_inclusive( 1 . into( ) ) ) ;
419
+ assert ! ( r( 1 , 3 ) . contains_inclusive( 2 . into( ) ) ) ;
420
+ assert ! ( r( 1 , 3 ) . contains_inclusive( 3 . into( ) ) ) ;
421
+ assert ! ( !r( 1 , 3 ) . contains_inclusive( 4 . into( ) ) ) ;
422
+ }
387
423
}
0 commit comments