@@ -424,6 +424,32 @@ impl<T: Debug + PrimInt> Vob<T> {
424424 Some ( blk & ( T :: one ( ) << ( index % bits_per_block :: < T > ( ) ) ) != T :: zero ( ) )
425425 }
426426
427+ /// Returns the value of the element at position `index`. This is done without doing bounds
428+ /// checking. For a safe alternative see [`get`].
429+ ///
430+ /// # Safety
431+ ///
432+ /// Calling this method with an out-of-bounds index is *[undefined behavior]*
433+ ///
434+ /// You can think of this like `.get(index).unwrap_unchecked()`.
435+ ///
436+ /// [`get`]: crate::Vob::get
437+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
438+ ///
439+ /// # Examples
440+ /// ```
441+ /// use vob::Vob;
442+ /// let mut v = Vob::new();
443+ /// v.push(false);
444+ /// unsafe {
445+ /// assert_eq!(v.get_unchecked(0), false);
446+ /// }
447+ /// ```
448+ pub unsafe fn get_unchecked ( & self , index : usize ) -> bool {
449+ let blk = * self . vec . get_unchecked ( block_offset :: < T > ( index) ) ;
450+ blk & ( T :: one ( ) << ( index % bits_per_block :: < T > ( ) ) ) != T :: zero ( )
451+ }
452+
427453 /// Sets the value of the element at position `index`. Returns `true` if this led to a change
428454 /// in the underlying storage or `false` otherwise.
429455 ///
@@ -460,6 +486,43 @@ impl<T: Debug + PrimInt> Vob<T> {
460486 }
461487 }
462488
489+ /// Sets the value of the element at position `index`. Returns `true` if this led to a change
490+ /// in the underlying storage or `false` otherwise. This is done without doing bounds
491+ /// checking. For a safe alternative see [`set`].
492+ ///
493+ /// # Safety
494+ ///
495+ /// Calling this method with an out-of-bounds index is *[undefined behavior]*
496+ ///
497+ /// [`set`]: crate::Vob::set
498+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
499+ ///
500+ /// # Examples
501+ /// ```
502+ /// use vob::Vob;
503+ /// let mut v = Vob::new();
504+ /// v.push(false);
505+ /// unsafe {
506+ /// v.set_unchecked(0, true);
507+ /// assert_eq!(v.get_unchecked(0), true);
508+ /// assert_eq!(v.set_unchecked(0, false), true);
509+ /// assert_eq!(v.set_unchecked(0, false), false);
510+ /// assert_eq!(v.get_unchecked(0), false);
511+ /// }
512+ /// ```
513+ pub unsafe fn set_unchecked ( & mut self , index : usize , value : bool ) -> bool {
514+ let msk = T :: one ( ) << ( index % bits_per_block :: < T > ( ) ) ;
515+ let off = block_offset :: < T > ( index) ;
516+ let old_v = * self . vec . get_unchecked ( off) ;
517+ let new_v = if value { old_v | msk } else { old_v & !msk } ;
518+ if new_v != old_v {
519+ * self . vec . get_unchecked_mut ( off) = new_v;
520+ true
521+ } else {
522+ false
523+ }
524+ }
525+
463526 /// Returns an iterator over the slice.
464527 ///
465528 /// # Examples
@@ -1188,11 +1251,13 @@ impl<T: Debug + PrimInt> Iterator for StorageIter<'_, T> {
11881251 }
11891252}
11901253
1254+ #[ inline( always) ]
11911255/// How many bits are stored in each underlying storage block?
11921256fn bits_per_block < T > ( ) -> usize {
11931257 bytes_per_block :: < T > ( ) * 8
11941258}
11951259
1260+ #[ inline( always) ]
11961261/// How many bytes are stored in each underlying storage block?
11971262fn bytes_per_block < T > ( ) -> usize {
11981263 size_of :: < T > ( )
@@ -1510,11 +1575,18 @@ mod tests {
15101575 assert_eq ! ( v. get( size_of:: <u8 >( ) * 8 ) , Some ( true ) ) ;
15111576 v. set ( size_of :: < u8 > ( ) * 8 , false ) ;
15121577 assert_eq ! ( v. get( size_of:: <u8 >( ) * 8 ) , Some ( false ) ) ;
1578+ unsafe {
1579+ assert_eq ! ( v. get_unchecked( size_of:: <u8 >( ) * 8 ) , false ) ;
1580+ }
15131581 assert_eq ! ( v. get( size_of:: <u8 >( ) * 8 + 1 ) , None ) ;
15141582 assert_eq ! ( v. set( size_of:: <u8 >( ) * 8 , true ) , true ) ;
15151583 assert_eq ! ( v. set( size_of:: <u8 >( ) * 8 , true ) , false ) ;
15161584 assert_eq ! ( v. get( size_of:: <u8 >( ) * 8 - 1 ) , Some ( true ) ) ;
15171585 assert_eq ! ( v. get( size_of:: <u8 >( ) * 8 - 2 ) , Some ( true ) ) ;
1586+ unsafe {
1587+ assert_eq ! ( v. get_unchecked( size_of:: <u8 >( ) * 8 - 2 ) , true ) ;
1588+ assert_eq ! ( v. set_unchecked( size_of:: <u8 >( ) * 8 - 2 , true ) , false ) ;
1589+ }
15181590 }
15191591
15201592 #[ test]
@@ -1565,6 +1637,10 @@ mod tests {
15651637 assert_eq ! ( v. set( size_of:: <usize >( ) * 8 , true ) , false ) ;
15661638 assert_eq ! ( v. get( size_of:: <usize >( ) * 8 - 1 ) , Some ( true ) ) ;
15671639 assert_eq ! ( v. get( size_of:: <usize >( ) * 8 - 2 ) , Some ( true ) ) ;
1640+ unsafe {
1641+ assert_eq ! ( v. get_unchecked( size_of:: <usize >( ) * 8 - 2 ) , true ) ;
1642+ assert_eq ! ( v. set_unchecked( size_of:: <usize >( ) * 8 - 2 , true ) , false ) ;
1643+ }
15681644 }
15691645
15701646 #[ test]
@@ -1858,6 +1934,23 @@ mod tests {
18581934 }
18591935 }
18601936
1937+ #[ test]
1938+ fn test_unchecked ( ) {
1939+ unsafe {
1940+ for len_a in 0 ..128 {
1941+ let mut a = random_vob ( len_a as usize ) ;
1942+ let mut b = a. clone ( ) ;
1943+ for i in 0 ..len_a {
1944+ assert_eq ! ( a. get( i) . unwrap( ) , b. get_unchecked( i) ) ;
1945+ assert_eq ! ( a. set( i, false ) , b. set_unchecked( i, false ) ) ;
1946+ assert ! ( !b. get_unchecked( i) ) ;
1947+ assert_eq ! ( a. set( i, true ) , b. set_unchecked( i, true ) ) ;
1948+ assert ! ( b. get_unchecked( i) ) ;
1949+ }
1950+ }
1951+ }
1952+ }
1953+
18611954 #[ test]
18621955 fn push_adjusts_vec_correctly ( ) {
18631956 let mut v = Vob :: new ( ) ;
0 commit comments