@@ -45,11 +45,17 @@ impl<T: NativePType> PVectorMut<T> {
4545 } )
4646 }
4747
48- /// Gets a nullable element at the given index.
48+ /// Gets a nullable element at the given index, **WITHOUT** bounds checking .
4949 ///
5050 /// If the element at the given index is null, returns `None`. Otherwise, returns `Some(x)`,
5151 /// where `x: T`.
5252 ///
53+ /// Note that this `get` method is different from the standard library [`slice::get`], which
54+ /// returns `None` if the index is out of bounds. This method will panic if the index is out of
55+ /// bounds, and return `None` if the elements is null.
56+ ///
57+ /// If you want bounds checking, use [`get_checked()`](Self::get_checked) instead.
58+ ///
5359 /// # Panics
5460 ///
5561 /// Panics if the index is out of bounds.
@@ -130,23 +136,23 @@ impl<T: NativePType> PVectorMut<T> {
130136 /// Returns an immutable slice over the internal mutable buffer with elements of type `T`.
131137 ///
132138 /// Note that this slice may contain garbage data where the [`validity()`] mask from the frozen
133- /// [`PVector`] type states that an element is invalid.
139+ /// [`PVector`](crate::PVector) type states that an element is invalid.
134140 ///
135141 /// The caller should check the frozen [`validity()`] before performing any operations.
136142 ///
137- /// [`validity()`]: PVector::validity
143+ /// [`validity()`]: crate:: PVector::validity
138144 pub fn as_slice ( & self ) -> & [ T ] {
139145 self . elements . as_slice ( )
140146 }
141147
142148 /// Returns a mutable slice over the internal mutable buffer with elements of type `T`.
143149 ///
144150 /// Note that this slice may contain garbage data where the [`validity()`] mask from the frozen
145- /// [`PVector`] type states that an element is invalid.
151+ /// [`PVector`](crate::PVector) type states that an element is invalid.
146152 ///
147153 /// The caller should check the frozen [`validity()`] before performing any operations.
148154 ///
149- /// [`validity()`]: PVector::validity
155+ /// [`validity()`]: crate:: PVector::validity
150156 pub fn as_mut_slice ( & mut self ) -> & mut [ T ] {
151157 self . elements . as_mut_slice ( )
152158 }
@@ -287,3 +293,217 @@ impl<T: NativePType> FromIterator<T> for PVectorMut<T> {
287293 vec
288294 }
289295}
296+
297+ #[ cfg( test) ]
298+ mod tests {
299+ use super :: * ;
300+ use crate :: VectorOps ;
301+
302+ #[ test]
303+ fn test_first_last ( ) {
304+ let empty = PVectorMut :: < i32 > :: with_capacity ( 0 ) ;
305+ assert_eq ! ( empty. first( ) , None ) ;
306+ assert_eq ! ( empty. last( ) , None ) ;
307+
308+ let single = PVectorMut :: from_iter ( [ Some ( 42 ) ] ) ;
309+ assert_eq ! ( single. first( ) , Some ( Some ( 42 ) ) ) ;
310+ assert_eq ! ( single. last( ) , Some ( Some ( 42 ) ) ) ;
311+
312+ let mixed = PVectorMut :: from_iter ( [ Some ( 1 ) , None , Some ( 3 ) , None , Some ( 5 ) ] ) ;
313+ assert_eq ! ( mixed. first( ) , Some ( Some ( 1 ) ) ) ;
314+ assert_eq ! ( mixed. last( ) , Some ( Some ( 5 ) ) ) ;
315+
316+ let null_first = PVectorMut :: from_iter ( [ None , Some ( 2i32 ) ] ) ;
317+ assert_eq ! ( null_first. first( ) , Some ( None ) ) ;
318+ assert_eq ! ( null_first. last( ) , Some ( Some ( 2 ) ) ) ;
319+ }
320+
321+ #[ test]
322+ fn test_get_methods ( ) {
323+ let vec = PVectorMut :: from_iter ( [ Some ( 1 ) , None , Some ( 3 ) , None , Some ( 5 ) ] ) ;
324+
325+ // Test get_checked - bounds and nulls.
326+ assert_eq ! ( vec. get_checked( 0 ) , Some ( Some ( 1 ) ) ) ;
327+ assert_eq ! ( vec. get_checked( 1 ) , Some ( None ) ) ;
328+ assert_eq ! ( vec. get_checked( 5 ) , None ) ; // Out of bounds.
329+
330+ // Test get - nulls.
331+ assert_eq ! ( vec. get( 0 ) , Some ( 1 ) ) ;
332+ assert_eq ! ( vec. get( 1 ) , None ) ;
333+ assert_eq ! ( vec. get( 2 ) , Some ( 3 ) ) ;
334+
335+ // Test get_unchecked.
336+ unsafe {
337+ assert_eq ! ( vec. get_unchecked( 0 ) , 1 ) ;
338+ assert_eq ! ( vec. get_unchecked( 2 ) , 3 ) ;
339+ // Note: get_unchecked(1) would return default value but is safe.
340+ }
341+
342+ // Also test PVector methods.
343+ let frozen = vec. freeze ( ) ;
344+ assert_eq ! ( frozen. get_checked( 0 ) , Some ( Some ( 1 ) ) ) ;
345+ assert_eq ! ( frozen. get( 1 ) , None ) ;
346+ unsafe {
347+ assert_eq ! ( frozen. get_unchecked( 2 ) , 3 ) ;
348+ }
349+ }
350+
351+ #[ test]
352+ #[ should_panic( expected = "index out of bounds" ) ]
353+ fn test_get_panic ( ) {
354+ let vec = PVectorMut :: from_iter ( [ Some ( 1 ) , Some ( 2 ) ] ) ;
355+ let _ = vec. get ( 10 ) ;
356+ }
357+
358+ #[ test]
359+ fn test_push_variants ( ) {
360+ let mut vec = PVectorMut :: < i32 > :: with_capacity ( 10 ) ;
361+ vec. push ( 1 ) ;
362+ vec. push_opt ( None ) ;
363+ vec. push_opt ( Some ( 3 ) ) ;
364+
365+ assert_eq ! ( vec. len( ) , 3 ) ;
366+ assert_eq ! ( vec. get( 0 ) , Some ( 1 ) ) ;
367+ assert_eq ! ( vec. get( 1 ) , None ) ;
368+ assert_eq ! ( vec. get( 2 ) , Some ( 3 ) ) ;
369+
370+ // Test push_unchecked with pre-reserved capacity.
371+ vec. reserve ( 1 ) ;
372+ unsafe {
373+ vec. push_unchecked ( 4 ) ;
374+ }
375+ assert_eq ! ( vec. get( 3 ) , Some ( 4 ) ) ;
376+ }
377+
378+ #[ test]
379+ fn test_resize_operations ( ) {
380+ let mut vec = PVectorMut :: from_iter ( [ 1i32 , 2 , 3 ] ) ;
381+
382+ // Grow with valid values.
383+ vec. resize ( 5 , Some ( 99 ) ) ;
384+ assert_eq ! ( vec. len( ) , 5 ) ;
385+ assert_eq ! ( vec. get( 3 ) , Some ( 99 ) ) ;
386+ assert_eq ! ( vec. get( 4 ) , Some ( 99 ) ) ;
387+
388+ // Grow with nulls.
389+ vec. resize ( 7 , None ) ;
390+ assert_eq ! ( vec. get( 5 ) , None ) ;
391+ assert_eq ! ( vec. get( 6 ) , None ) ;
392+
393+ // Shrink.
394+ vec. resize ( 2 , Some ( 0 ) ) ;
395+ assert_eq ! ( vec. len( ) , 2 ) ;
396+ assert_eq ! ( vec. get( 0 ) , Some ( 1 ) ) ;
397+ assert_eq ! ( vec. get( 1 ) , Some ( 2 ) ) ;
398+ }
399+
400+ #[ test]
401+ fn test_clear_truncate ( ) {
402+ let mut vec = PVectorMut :: from_iter ( [ Some ( 1 ) , None , Some ( 3 ) , None , Some ( 5 ) ] ) ;
403+ let cap = vec. capacity ( ) ;
404+
405+ vec. truncate ( 3 ) ;
406+ assert_eq ! ( vec. len( ) , 3 ) ;
407+ assert_eq ! ( vec. last( ) , Some ( Some ( 3 ) ) ) ;
408+ assert ! ( vec. capacity( ) >= cap) ; // Capacity preserved.
409+
410+ vec. truncate ( 10 ) ; // Truncate beyond length - no-op.
411+ assert_eq ! ( vec. len( ) , 3 ) ;
412+
413+ vec. clear ( ) ;
414+ assert_eq ! ( vec. len( ) , 0 ) ;
415+ assert ! ( vec. capacity( ) >= cap) ; // Capacity still preserved.
416+ assert_eq ! ( vec. first( ) , None ) ;
417+ }
418+
419+ #[ test]
420+ fn test_slice_access ( ) {
421+ let mut vec = PVectorMut :: from_iter ( [ Some ( 1i32 ) , None , Some ( 3 ) ] ) ;
422+ let slice = vec. as_slice ( ) ;
423+ assert_eq ! ( slice[ 0 ] , 1 ) ;
424+ assert_eq ! ( slice[ 2 ] , 3 ) ;
425+ // slice[1] is undefined for null but safe to access.
426+
427+ let mut_slice = vec. as_mut_slice ( ) ;
428+ mut_slice[ 0 ] = 10 ;
429+ assert_eq ! ( vec. get( 0 ) , Some ( 10 ) ) ;
430+
431+ let frozen = vec. freeze ( ) ;
432+ assert_eq ! ( frozen. as_slice( ) [ 0 ] , 10 ) ;
433+ }
434+
435+ #[ test]
436+ fn test_from_iter_variants ( ) {
437+ // FromIterator<T> - all non-null.
438+ let vec1 = PVectorMut :: from_iter ( [ 1i32 , 2 , 3 ] ) ;
439+ assert_eq ! ( vec1. len( ) , 3 ) ;
440+ assert ! ( vec1. freeze( ) . validity( ) . all_true( ) ) ;
441+
442+ // FromIterator<Option<T>> - mixed null/non-null.
443+ let vec2 = PVectorMut :: from_iter ( [ Some ( 1i32 ) , None , Some ( 3 ) ] ) ;
444+ assert_eq ! ( vec2. len( ) , 3 ) ;
445+ assert_eq ! ( vec2. freeze( ) . validity( ) . true_count( ) , 2 ) ;
446+
447+ // Empty iterators.
448+ let empty1 = PVectorMut :: from_iter :: < [ i32 ; 0 ] > ( [ ] ) ;
449+ let empty2 = PVectorMut :: < i32 > :: from_iter ( std:: iter:: empty :: < Option < i32 > > ( ) ) ;
450+ assert_eq ! ( empty1. len( ) , 0 ) ;
451+ assert_eq ! ( empty2. len( ) , 0 ) ;
452+ }
453+
454+ #[ test]
455+ fn test_extend_operations ( ) {
456+ let mut vec = PVectorMut :: from_iter ( [ 1i32 , 2 ] ) ;
457+
458+ // Extend<T> - all non-null.
459+ vec. extend ( [ 3 , 4 ] ) ;
460+ assert_eq ! ( vec. len( ) , 4 ) ;
461+ assert_eq ! ( vec. get( 3 ) , Some ( 4 ) ) ;
462+
463+ // Extend<Option<T>> - mixed null/non-null.
464+ vec. extend ( [ Some ( 5 ) , None , Some ( 7 ) ] ) ;
465+ assert_eq ! ( vec. len( ) , 7 ) ;
466+ assert_eq ! ( vec. get( 5 ) , None ) ;
467+ assert_eq ! ( vec. get( 6 ) , Some ( 7 ) ) ;
468+
469+ // Extend with iterator that has size hint.
470+ let iter = 8 ..10 ;
471+ vec. extend ( iter) ;
472+ assert_eq ! ( vec. get( 8 ) , Some ( 9 ) ) ;
473+ }
474+
475+ #[ test]
476+ fn test_empty_vector_edge_cases ( ) {
477+ let empty = PVectorMut :: < i32 > :: with_capacity ( 0 ) ;
478+ assert_eq ! ( empty. len( ) , 0 ) ;
479+ assert_eq ! ( empty. first( ) , None ) ;
480+ assert_eq ! ( empty. last( ) , None ) ;
481+ assert_eq ! ( empty. get_checked( 0 ) , None ) ;
482+ assert_eq ! ( empty. as_slice( ) . len( ) , 0 ) ;
483+
484+ let mut mutable_empty = PVectorMut :: < i32 > :: with_capacity ( 0 ) ;
485+ mutable_empty. clear ( ) ; // No-op on empty.
486+ mutable_empty. truncate ( 0 ) ; // No-op.
487+ mutable_empty. resize ( 0 , None ) ; // No-op.
488+ assert_eq ! ( mutable_empty. len( ) , 0 ) ;
489+ }
490+
491+ #[ test]
492+ fn test_complex_workflow ( ) {
493+ // Integration test combining multiple operations.
494+ let mut vec = PVectorMut :: < i32 > :: with_capacity ( 2 ) ;
495+ vec. extend ( [ 1 , 2 ] ) ; // Extend<T>.
496+ vec. push_opt ( None ) ;
497+ vec. resize ( 5 , Some ( 99 ) ) ;
498+ vec. truncate ( 4 ) ;
499+ vec. extend ( [ Some ( 10 ) , None ] ) ; // Extend<Option<T>>.
500+
501+ assert_eq ! ( vec. len( ) , 6 ) ;
502+ let frozen = vec. freeze ( ) ;
503+ assert_eq ! ( frozen. validity( ) . true_count( ) , 4 ) ;
504+ assert_eq ! ( frozen. get( 0 ) , Some ( 1 ) ) ;
505+ assert_eq ! ( frozen. get( 2 ) , None ) ;
506+ assert_eq ! ( frozen. get( 3 ) , Some ( 99 ) ) ;
507+ assert_eq ! ( frozen. get( 5 ) , None ) ;
508+ }
509+ }
0 commit comments