@@ -28,6 +28,11 @@ impl TextUnit {
28
28
}
29
29
TextUnit ( s. len ( ) as u32 )
30
30
}
31
+
32
+ #[ inline( always) ]
33
+ pub fn checked_sub ( self , other : TextUnit ) -> Option < TextUnit > {
34
+ self . 0 . checked_sub ( other. 0 ) . map ( TextUnit )
35
+ }
31
36
}
32
37
33
38
impl fmt:: Debug for TextUnit {
@@ -199,6 +204,17 @@ pub struct TextRange {
199
204
end : TextUnit ,
200
205
}
201
206
207
+ impl TextRange {
208
+ #[ inline( always) ]
209
+ pub fn checked_sub ( self , other : TextUnit ) -> Option < TextRange > {
210
+ let res = TextRange :: offset_len (
211
+ self . start ( ) . checked_sub ( other) ?,
212
+ self . len ( )
213
+ ) ;
214
+ Some ( res)
215
+ }
216
+ }
217
+
202
218
impl fmt:: Debug for TextRange {
203
219
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
204
220
<Self as fmt:: Display >:: fmt ( self , f)
@@ -325,4 +341,15 @@ mod tests {
325
341
TextRange :: from_to( 5 . into( ) , 15 . into( ) ) ,
326
342
) ;
327
343
}
344
+
345
+ #[ test]
346
+ fn test_checked_ops ( ) {
347
+ let x: TextUnit = 1 . into ( ) ;
348
+ assert_eq ! ( x. checked_sub( 1 . into( ) ) , Some ( 0 . into( ) ) ) ;
349
+ assert_eq ! ( x. checked_sub( 2 . into( ) ) , None ) ;
350
+
351
+ let r = TextRange :: from_to ( 1 . into ( ) , 2 . into ( ) ) ;
352
+ assert_eq ! ( r. checked_sub( 1 . into( ) ) , Some ( TextRange :: from_to( 0 . into( ) , 1 . into( ) ) ) ) ;
353
+ assert_eq ! ( x. checked_sub( 2 . into( ) ) , None ) ;
354
+ }
328
355
}
0 commit comments