1
+ use safety:: requires;
2
+
1
3
use super :: {
2
4
FusedIterator , TrustedLen , TrustedRandomAccess , TrustedRandomAccessNoCoerce , TrustedStep ,
3
5
} ;
4
6
use crate :: ascii:: Char as AsciiChar ;
7
+ #[ cfg( kani) ]
8
+ use crate :: kani;
5
9
use crate :: mem;
6
10
use crate :: net:: { Ipv4Addr , Ipv6Addr } ;
7
11
use crate :: num:: NonZero ;
@@ -184,12 +188,14 @@ pub trait Step: Clone + PartialOrd + Sized {
184
188
// than the signed::MAX value. Therefore `as` casting to the signed type would be incorrect.
185
189
macro_rules! step_signed_methods {
186
190
( $unsigned: ty) => {
191
+ #[ requires( start. checked_add_unsigned( n as $unsigned) . is_some( ) ) ]
187
192
#[ inline]
188
193
unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
189
194
// SAFETY: the caller has to guarantee that `start + n` doesn't overflow.
190
195
unsafe { start. checked_add_unsigned( n as $unsigned) . unwrap_unchecked( ) }
191
196
}
192
197
198
+ #[ requires( start. checked_sub_unsigned( n as $unsigned) . is_some( ) ) ]
193
199
#[ inline]
194
200
unsafe fn backward_unchecked( start: Self , n: usize ) -> Self {
195
201
// SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
@@ -200,12 +206,14 @@ macro_rules! step_signed_methods {
200
206
201
207
macro_rules! step_unsigned_methods {
202
208
( ) => {
209
+ #[ requires( start. checked_add( n as Self ) . is_some( ) ) ]
203
210
#[ inline]
204
211
unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
205
212
// SAFETY: the caller has to guarantee that `start + n` doesn't overflow.
206
213
unsafe { start. unchecked_add( n as Self ) }
207
214
}
208
215
216
+ #[ requires( start >= ( n as Self ) ) ]
209
217
#[ inline]
210
218
unsafe fn backward_unchecked( start: Self , n: usize ) -> Self {
211
219
// SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
@@ -495,6 +503,13 @@ impl Step for char {
495
503
Some ( unsafe { char:: from_u32_unchecked ( res) } )
496
504
}
497
505
506
+ #[ requires( {
507
+ ( start as u32 ) . checked_add( count as u32 ) . is_some_and( |dist|
508
+ ( start as u32 ) >= 0xD800 ||
509
+ dist < 0xD800 ||
510
+ dist. checked_add( 0x800 ) . is_some( )
511
+ )
512
+ } ) ]
498
513
#[ inline]
499
514
unsafe fn forward_unchecked ( start : char , count : usize ) -> char {
500
515
let start = start as u32 ;
@@ -511,6 +526,13 @@ impl Step for char {
511
526
unsafe { char:: from_u32_unchecked ( res) }
512
527
}
513
528
529
+ #[ requires( {
530
+ ( start as u32 ) . checked_sub( count as u32 ) . is_some_and( |dist|
531
+ ( start as u32 ) < 0xE000 ||
532
+ dist >= 0xE000 ||
533
+ dist. checked_sub( 0x800 ) . is_some( )
534
+ )
535
+ } ) ]
514
536
#[ inline]
515
537
unsafe fn backward_unchecked ( start : char , count : usize ) -> char {
516
538
let start = start as u32 ;
@@ -549,6 +571,7 @@ impl Step for AsciiChar {
549
571
Some ( unsafe { AsciiChar :: from_u8_unchecked ( end) } )
550
572
}
551
573
574
+ #[ requires( count < 256 && start. to_u8( ) . checked_add( count as u8 ) . is_some( ) ) ]
552
575
#[ inline]
553
576
unsafe fn forward_unchecked ( start : AsciiChar , count : usize ) -> AsciiChar {
554
577
// SAFETY: Caller asserts that result is a valid ASCII character,
@@ -559,6 +582,7 @@ impl Step for AsciiChar {
559
582
unsafe { AsciiChar :: from_u8_unchecked ( end) }
560
583
}
561
584
585
+ #[ requires( count < 256 && start. to_u8( ) . checked_sub( count as u8 ) . is_some( ) ) ]
562
586
#[ inline]
563
587
unsafe fn backward_unchecked ( start : AsciiChar , count : usize ) -> AsciiChar {
564
588
// SAFETY: Caller asserts that result is a valid ASCII character,
@@ -587,13 +611,15 @@ impl Step for Ipv4Addr {
587
611
u32:: backward_checked ( start. to_bits ( ) , count) . map ( Ipv4Addr :: from_bits)
588
612
}
589
613
614
+ #[ requires( start. to_bits( ) . checked_add( count as u32 ) . is_some( ) ) ]
590
615
#[ inline]
591
616
unsafe fn forward_unchecked ( start : Ipv4Addr , count : usize ) -> Ipv4Addr {
592
617
// SAFETY: Since u32 and Ipv4Addr are losslessly convertible,
593
618
// this is as safe as the u32 version.
594
619
Ipv4Addr :: from_bits ( unsafe { u32:: forward_unchecked ( start. to_bits ( ) , count) } )
595
620
}
596
621
622
+ #[ requires( start. to_bits( ) . checked_sub( count as u32 ) . is_some( ) ) ]
597
623
#[ inline]
598
624
unsafe fn backward_unchecked ( start : Ipv4Addr , count : usize ) -> Ipv4Addr {
599
625
// SAFETY: Since u32 and Ipv4Addr are losslessly convertible,
@@ -619,13 +645,15 @@ impl Step for Ipv6Addr {
619
645
u128:: backward_checked ( start. to_bits ( ) , count) . map ( Ipv6Addr :: from_bits)
620
646
}
621
647
648
+ #[ requires( start. to_bits( ) . checked_add( count as u128 ) . is_some( ) ) ]
622
649
#[ inline]
623
650
unsafe fn forward_unchecked ( start : Ipv6Addr , count : usize ) -> Ipv6Addr {
624
651
// SAFETY: Since u128 and Ipv6Addr are losslessly convertible,
625
652
// this is as safe as the u128 version.
626
653
Ipv6Addr :: from_bits ( unsafe { u128:: forward_unchecked ( start. to_bits ( ) , count) } )
627
654
}
628
655
656
+ #[ requires( start. to_bits( ) . checked_sub( count as u128 ) . is_some( ) ) ]
629
657
#[ inline]
630
658
unsafe fn backward_unchecked ( start : Ipv6Addr , count : usize ) -> Ipv6Addr {
631
659
// SAFETY: Since u128 and Ipv6Addr are losslessly convertible,
0 commit comments