@@ -5508,4 +5508,329 @@ mod verify {
55085508 let mut a: [ u8 ; 100 ] = kani:: any ( ) ;
55095509 a. reverse ( ) ;
55105510 }
5511+
5512+ // =========================================================================
5513+ // Challenge 17: Const generic function harnesses
5514+ // =========================================================================
5515+
5516+ // --- first_chunk / first_chunk_mut ---
5517+ macro_rules! check_first_chunk {
5518+ ( $name: ident, $N: expr) => {
5519+ #[ kani:: proof]
5520+ fn $name( ) {
5521+ const ARR_SIZE : usize = 64 ;
5522+ let arr: [ u8 ; ARR_SIZE ] = kani:: any( ) ;
5523+ let slice = kani:: slice:: any_slice_of_array( & arr) ;
5524+ let result = slice. first_chunk:: <$N>( ) ;
5525+ if slice. len( ) >= $N {
5526+ assert!( result. is_some( ) ) ;
5527+ } else {
5528+ assert!( result. is_none( ) ) ;
5529+ }
5530+ }
5531+ } ;
5532+ }
5533+ check_first_chunk ! ( check_first_chunk_0, 0 ) ;
5534+ check_first_chunk ! ( check_first_chunk_1, 1 ) ;
5535+ check_first_chunk ! ( check_first_chunk_2, 2 ) ;
5536+ check_first_chunk ! ( check_first_chunk_4, 4 ) ;
5537+ check_first_chunk ! ( check_first_chunk_8, 8 ) ;
5538+
5539+ macro_rules! check_first_chunk_mut {
5540+ ( $name: ident, $N: expr) => {
5541+ #[ kani:: proof]
5542+ fn $name( ) {
5543+ const ARR_SIZE : usize = 64 ;
5544+ let mut arr: [ u8 ; ARR_SIZE ] = kani:: any( ) ;
5545+ let slice = kani:: slice:: any_slice_of_array_mut( & mut arr) ;
5546+ let result = slice. first_chunk_mut:: <$N>( ) ;
5547+ if slice. len( ) >= $N {
5548+ assert!( result. is_some( ) ) ;
5549+ } else {
5550+ assert!( result. is_none( ) ) ;
5551+ }
5552+ }
5553+ } ;
5554+ }
5555+ check_first_chunk_mut ! ( check_first_chunk_mut_0, 0 ) ;
5556+ check_first_chunk_mut ! ( check_first_chunk_mut_1, 1 ) ;
5557+ check_first_chunk_mut ! ( check_first_chunk_mut_4, 4 ) ;
5558+
5559+ // --- split_first_chunk / split_first_chunk_mut ---
5560+ macro_rules! check_split_first_chunk {
5561+ ( $name: ident, $N: expr) => {
5562+ #[ kani:: proof]
5563+ fn $name( ) {
5564+ const ARR_SIZE : usize = 64 ;
5565+ let arr: [ u8 ; ARR_SIZE ] = kani:: any( ) ;
5566+ let slice = kani:: slice:: any_slice_of_array( & arr) ;
5567+ let result = slice. split_first_chunk:: <$N>( ) ;
5568+ if slice. len( ) >= $N {
5569+ let ( first, rest) = result. unwrap( ) ;
5570+ assert!( first. len( ) == $N) ;
5571+ assert!( rest. len( ) == slice. len( ) - $N) ;
5572+ } else {
5573+ assert!( result. is_none( ) ) ;
5574+ }
5575+ }
5576+ } ;
5577+ }
5578+ check_split_first_chunk ! ( check_split_first_chunk_0, 0 ) ;
5579+ check_split_first_chunk ! ( check_split_first_chunk_1, 1 ) ;
5580+ check_split_first_chunk ! ( check_split_first_chunk_4, 4 ) ;
5581+
5582+ macro_rules! check_split_first_chunk_mut {
5583+ ( $name: ident, $N: expr) => {
5584+ #[ kani:: proof]
5585+ fn $name( ) {
5586+ const ARR_SIZE : usize = 64 ;
5587+ let mut arr: [ u8 ; ARR_SIZE ] = kani:: any( ) ;
5588+ let slice = kani:: slice:: any_slice_of_array_mut( & mut arr) ;
5589+ let len = slice. len( ) ;
5590+ let result = slice. split_first_chunk_mut:: <$N>( ) ;
5591+ if len >= $N {
5592+ let ( first, rest) = result. unwrap( ) ;
5593+ assert!( first. len( ) == $N) ;
5594+ assert!( rest. len( ) == len - $N) ;
5595+ } else {
5596+ assert!( result. is_none( ) ) ;
5597+ }
5598+ }
5599+ } ;
5600+ }
5601+ check_split_first_chunk_mut ! ( check_split_first_chunk_mut_0, 0 ) ;
5602+ check_split_first_chunk_mut ! ( check_split_first_chunk_mut_1, 1 ) ;
5603+ check_split_first_chunk_mut ! ( check_split_first_chunk_mut_4, 4 ) ;
5604+
5605+ // --- split_last_chunk / split_last_chunk_mut ---
5606+ macro_rules! check_split_last_chunk {
5607+ ( $name: ident, $N: expr) => {
5608+ #[ kani:: proof]
5609+ fn $name( ) {
5610+ const ARR_SIZE : usize = 64 ;
5611+ let arr: [ u8 ; ARR_SIZE ] = kani:: any( ) ;
5612+ let slice = kani:: slice:: any_slice_of_array( & arr) ;
5613+ let result = slice. split_last_chunk:: <$N>( ) ;
5614+ if slice. len( ) >= $N {
5615+ let ( rest, last) = result. unwrap( ) ;
5616+ assert!( last. len( ) == $N) ;
5617+ assert!( rest. len( ) == slice. len( ) - $N) ;
5618+ } else {
5619+ assert!( result. is_none( ) ) ;
5620+ }
5621+ }
5622+ } ;
5623+ }
5624+ check_split_last_chunk ! ( check_split_last_chunk_0, 0 ) ;
5625+ check_split_last_chunk ! ( check_split_last_chunk_1, 1 ) ;
5626+ check_split_last_chunk ! ( check_split_last_chunk_4, 4 ) ;
5627+
5628+ macro_rules! check_split_last_chunk_mut {
5629+ ( $name: ident, $N: expr) => {
5630+ #[ kani:: proof]
5631+ fn $name( ) {
5632+ const ARR_SIZE : usize = 64 ;
5633+ let mut arr: [ u8 ; ARR_SIZE ] = kani:: any( ) ;
5634+ let slice = kani:: slice:: any_slice_of_array_mut( & mut arr) ;
5635+ let len = slice. len( ) ;
5636+ let result = slice. split_last_chunk_mut:: <$N>( ) ;
5637+ if len >= $N {
5638+ let ( rest, last) = result. unwrap( ) ;
5639+ assert!( last. len( ) == $N) ;
5640+ assert!( rest. len( ) == len - $N) ;
5641+ } else {
5642+ assert!( result. is_none( ) ) ;
5643+ }
5644+ }
5645+ } ;
5646+ }
5647+ check_split_last_chunk_mut ! ( check_split_last_chunk_mut_0, 0 ) ;
5648+ check_split_last_chunk_mut ! ( check_split_last_chunk_mut_1, 1 ) ;
5649+ check_split_last_chunk_mut ! ( check_split_last_chunk_mut_4, 4 ) ;
5650+
5651+ // --- last_chunk / last_chunk_mut ---
5652+ macro_rules! check_last_chunk {
5653+ ( $name: ident, $N: expr) => {
5654+ #[ kani:: proof]
5655+ fn $name( ) {
5656+ const ARR_SIZE : usize = 64 ;
5657+ let arr: [ u8 ; ARR_SIZE ] = kani:: any( ) ;
5658+ let slice = kani:: slice:: any_slice_of_array( & arr) ;
5659+ let result = slice. last_chunk:: <$N>( ) ;
5660+ if slice. len( ) >= $N {
5661+ assert!( result. is_some( ) ) ;
5662+ } else {
5663+ assert!( result. is_none( ) ) ;
5664+ }
5665+ }
5666+ } ;
5667+ }
5668+ check_last_chunk ! ( check_last_chunk_0, 0 ) ;
5669+ check_last_chunk ! ( check_last_chunk_1, 1 ) ;
5670+ check_last_chunk ! ( check_last_chunk_4, 4 ) ;
5671+
5672+ macro_rules! check_last_chunk_mut {
5673+ ( $name: ident, $N: expr) => {
5674+ #[ kani:: proof]
5675+ fn $name( ) {
5676+ const ARR_SIZE : usize = 64 ;
5677+ let mut arr: [ u8 ; ARR_SIZE ] = kani:: any( ) ;
5678+ let slice = kani:: slice:: any_slice_of_array_mut( & mut arr) ;
5679+ let len = slice. len( ) ;
5680+ let result = slice. last_chunk_mut:: <$N>( ) ;
5681+ if len >= $N {
5682+ assert!( result. is_some( ) ) ;
5683+ } else {
5684+ assert!( result. is_none( ) ) ;
5685+ }
5686+ }
5687+ } ;
5688+ }
5689+ check_last_chunk_mut ! ( check_last_chunk_mut_0, 0 ) ;
5690+ check_last_chunk_mut ! ( check_last_chunk_mut_1, 1 ) ;
5691+ check_last_chunk_mut ! ( check_last_chunk_mut_4, 4 ) ;
5692+
5693+ // --- as_chunks_unchecked / as_chunks / as_rchunks ---
5694+ macro_rules! check_as_chunks {
5695+ ( $name: ident, $N: expr) => {
5696+ #[ kani:: proof]
5697+ fn $name( ) {
5698+ const ARR_SIZE : usize = 64 ;
5699+ let arr: [ u8 ; ARR_SIZE ] = kani:: any( ) ;
5700+ let slice = kani:: slice:: any_slice_of_array( & arr) ;
5701+ let ( chunks, remainder) = slice. as_chunks:: <$N>( ) ;
5702+ assert!( chunks. len( ) * $N + remainder. len( ) == slice. len( ) ) ;
5703+ assert!( remainder. len( ) < $N) ;
5704+ }
5705+ } ;
5706+ }
5707+ check_as_chunks ! ( check_as_chunks_1, 1 ) ;
5708+ check_as_chunks ! ( check_as_chunks_2, 2 ) ;
5709+ check_as_chunks ! ( check_as_chunks_4, 4 ) ;
5710+ check_as_chunks ! ( check_as_chunks_8, 8 ) ;
5711+
5712+ macro_rules! check_as_rchunks {
5713+ ( $name: ident, $N: expr) => {
5714+ #[ kani:: proof]
5715+ fn $name( ) {
5716+ const ARR_SIZE : usize = 64 ;
5717+ let arr: [ u8 ; ARR_SIZE ] = kani:: any( ) ;
5718+ let slice = kani:: slice:: any_slice_of_array( & arr) ;
5719+ let ( remainder, chunks) = slice. as_rchunks:: <$N>( ) ;
5720+ assert!( chunks. len( ) * $N + remainder. len( ) == slice. len( ) ) ;
5721+ assert!( remainder. len( ) < $N) ;
5722+ }
5723+ } ;
5724+ }
5725+ check_as_rchunks ! ( check_as_rchunks_1, 1 ) ;
5726+ check_as_rchunks ! ( check_as_rchunks_2, 2 ) ;
5727+ check_as_rchunks ! ( check_as_rchunks_4, 4 ) ;
5728+
5729+ // --- as_chunks_mut / as_chunks_unchecked_mut ---
5730+ macro_rules! check_as_chunks_mut {
5731+ ( $name: ident, $N: expr) => {
5732+ #[ kani:: proof]
5733+ fn $name( ) {
5734+ const ARR_SIZE : usize = 64 ;
5735+ let mut arr: [ u8 ; ARR_SIZE ] = kani:: any( ) ;
5736+ let slice = kani:: slice:: any_slice_of_array_mut( & mut arr) ;
5737+ let len = slice. len( ) ;
5738+ let ( chunks, remainder) = slice. as_chunks_mut:: <$N>( ) ;
5739+ assert!( chunks. len( ) * $N + remainder. len( ) == len) ;
5740+ assert!( remainder. len( ) < $N) ;
5741+ }
5742+ } ;
5743+ }
5744+ check_as_chunks_mut ! ( check_as_chunks_mut_1, 1 ) ;
5745+ check_as_chunks_mut ! ( check_as_chunks_mut_2, 2 ) ;
5746+ check_as_chunks_mut ! ( check_as_chunks_mut_4, 4 ) ;
5747+
5748+ // --- as_flattened / as_flattened_mut ---
5749+ macro_rules! check_as_flattened {
5750+ ( $name: ident, $N: expr) => {
5751+ #[ kani:: proof]
5752+ fn $name( ) {
5753+ const ARR_SIZE : usize = 16 ;
5754+ let arr: [ [ u8 ; $N] ; ARR_SIZE ] = kani:: any( ) ;
5755+ let slice: & [ [ u8 ; $N] ] = kani:: slice:: any_slice_of_array( & arr) ;
5756+ let flat = slice. as_flattened( ) ;
5757+ assert!( flat. len( ) == slice. len( ) * $N) ;
5758+ }
5759+ } ;
5760+ }
5761+ check_as_flattened ! ( check_as_flattened_1, 1 ) ;
5762+ check_as_flattened ! ( check_as_flattened_2, 2 ) ;
5763+ check_as_flattened ! ( check_as_flattened_4, 4 ) ;
5764+
5765+ macro_rules! check_as_flattened_mut {
5766+ ( $name: ident, $N: expr) => {
5767+ #[ kani:: proof]
5768+ fn $name( ) {
5769+ const ARR_SIZE : usize = 16 ;
5770+ let mut arr: [ [ u8 ; $N] ; ARR_SIZE ] = kani:: any( ) ;
5771+ let slice: & mut [ [ u8 ; $N] ] = kani:: slice:: any_slice_of_array_mut( & mut arr) ;
5772+ let flat = slice. as_flattened_mut( ) ;
5773+ assert!( flat. len( ) == slice. len( ) * $N) ;
5774+ }
5775+ } ;
5776+ }
5777+ check_as_flattened_mut ! ( check_as_flattened_mut_1, 1 ) ;
5778+ check_as_flattened_mut ! ( check_as_flattened_mut_2, 2 ) ;
5779+ check_as_flattened_mut ! ( check_as_flattened_mut_4, 4 ) ;
5780+
5781+ // --- get_unchecked / get_unchecked_mut ---
5782+ #[ kani:: proof]
5783+ fn check_get_unchecked ( ) {
5784+ const ARR_SIZE : usize = 64 ;
5785+ let arr: [ u8 ; ARR_SIZE ] = kani:: any ( ) ;
5786+ let slice = kani:: slice:: any_slice_of_array ( & arr) ;
5787+ if !slice. is_empty ( ) {
5788+ let idx: usize = kani:: any ( ) ;
5789+ kani:: assume ( idx < slice. len ( ) ) ;
5790+ let val = unsafe { slice. get_unchecked ( idx) } ;
5791+ assert ! ( * val == slice[ idx] ) ;
5792+ }
5793+ }
5794+
5795+ #[ kani:: proof]
5796+ fn check_get_unchecked_mut ( ) {
5797+ const ARR_SIZE : usize = 64 ;
5798+ let mut arr: [ u8 ; ARR_SIZE ] = kani:: any ( ) ;
5799+ let slice = kani:: slice:: any_slice_of_array_mut ( & mut arr) ;
5800+ if !slice. is_empty ( ) {
5801+ let idx: usize = kani:: any ( ) ;
5802+ kani:: assume ( idx < slice. len ( ) ) ;
5803+ let val = unsafe { slice. get_unchecked_mut ( idx) } ;
5804+ * val = 42 ;
5805+ }
5806+ }
5807+
5808+ // --- binary_search_by ---
5809+ #[ kani:: proof]
5810+ fn check_binary_search_by ( ) {
5811+ let arr: [ u8 ; 16 ] = kani:: any ( ) ;
5812+ let slice = kani:: slice:: any_slice_of_array ( & arr) ;
5813+ let target: u8 = kani:: any ( ) ;
5814+ // binary_search_by on unsorted slice should not panic or UB
5815+ let _ = slice. binary_search_by ( |x| x. cmp ( & target) ) ;
5816+ }
5817+
5818+ // --- copy_within ---
5819+ #[ kani:: proof]
5820+ fn check_copy_within ( ) {
5821+ const ARR_SIZE : usize = 16 ;
5822+ let mut arr: [ u8 ; ARR_SIZE ] = kani:: any ( ) ;
5823+ let slice = kani:: slice:: any_slice_of_array_mut ( & mut arr) ;
5824+ let len = slice. len ( ) ;
5825+ if len > 0 {
5826+ let src_start: usize = kani:: any ( ) ;
5827+ let src_end: usize = kani:: any ( ) ;
5828+ let dest: usize = kani:: any ( ) ;
5829+ kani:: assume ( src_start <= src_end) ;
5830+ kani:: assume ( src_end <= len) ;
5831+ let count = src_end - src_start;
5832+ kani:: assume ( dest <= len - count) ;
5833+ slice. copy_within ( src_start..src_end, dest) ;
5834+ }
5835+ }
55115836}
0 commit comments