@@ -3,6 +3,7 @@ use crate::consume::{consume_byte, consume_byte_arrays};
33use crate :: error:: error;
44use crate :: fast:: CowSlice ;
55use crate :: pack:: { invalid_packing, pack_bytes, unpack_bytes} ;
6+ use crate :: pack_shared:: PackingTrait ;
67use crate :: Error ;
78use alloc:: vec:: Vec ;
89use bytemuck:: Pod ;
@@ -19,7 +20,7 @@ enum Packing {
1920 _8,
2021}
2122
22- impl Packing {
23+ impl PackingTrait for Packing {
2324 fn new < T : SizedUInt > ( max : T ) -> Self {
2425 let max: u128 = max. try_into ( ) . unwrap_or_else ( |_| unreachable ! ( ) ) ; // From<usize> isn't implemented for u128.
2526 #[ allow( clippy:: match_overlapping_arm) ] // Just make sure not to reorder them.
@@ -37,7 +38,9 @@ impl Packing {
3738 // Also makes no packing with offset_by_min = true is unrepresentable.
3839 out. push ( ( self as u8 - Self :: new ( T :: MAX ) as u8 ) * 2 - offset_by_min as u8 ) ;
3940 }
41+ }
4042
43+ impl Packing {
4144 fn read < T : SizedUInt > ( input : & mut & [ u8 ] ) -> Result < ( Self , bool ) > {
4245 let v = consume_byte ( input) ?;
4346 let p_u8 = crate :: nightly:: div_ceil_u8 ( v, 2 ) + Self :: new ( T :: MAX ) as u8 ;
@@ -329,18 +332,8 @@ impl SizedUInt for u8 {
329332 }
330333}
331334
332- pub fn minmax < T : SizedInt > ( v : & [ T ] ) -> ( T , T ) {
333- let mut min = T :: MAX ;
334- let mut max = T :: MIN ;
335- for & v in v. iter ( ) {
336- min = min. min ( v) ;
337- max = max. max ( v) ;
338- }
339- ( min, max)
340- }
341-
342335fn skip_packing < T : SizedInt > ( length : usize ) -> bool {
343- // Be careful using size_of::<T> since usize can be 4 or 8 .
336+ // T is SizedInt, so it cannot be usize/isize, therefore comparisions against size are safe .
344337 if core:: mem:: size_of :: < T > ( ) == 1 {
345338 return true ; // u8s can't be packed by pack_ints (only pack_bytes).
346339 }
@@ -370,31 +363,9 @@ fn pack_ints_sized<T: SizedInt>(ints: &mut [T], out: &mut Vec<u8>) {
370363 let ( basic_packing, min_max) = if skip_packing :: < T > ( ints. len ( ) ) {
371364 ( Packing :: new ( T :: Unsigned :: MAX ) , None )
372365 } else {
373- // Take a small sample to avoid wastefully scanning the whole slice.
374- let ( sample, remaining) = ints. split_at ( ints. len ( ) . min ( 16 ) ) ;
375- let ( min, max) = minmax ( sample) ;
376-
377- // Only have to check packing(max - min) since it's always as good as packing(max).
378- let none = Packing :: new ( T :: Unsigned :: MAX ) ;
379- if Packing :: new ( max. to_unsigned ( ) . wrapping_sub ( min. to_unsigned ( ) ) ) == none {
380- none. write :: < T :: Unsigned > ( out, false ) ;
381- ( none, None )
382- } else {
383- let ( remaining_min, remaining_max) = minmax ( remaining) ;
384- let min = min. min ( remaining_min) ;
385- let max = max. max ( remaining_max) ;
386-
387- // Signed ints pack as unsigned ints if positive.
388- let basic_packing = if min >= T :: default ( ) {
389- Packing :: new ( max. to_unsigned ( ) )
390- } else {
391- none // Any negative can't be packed without offset_packing.
392- } ;
393- ( basic_packing, Some ( ( min, max) ) )
394- }
366+ crate :: pack_shared:: basic_packing_and_signed_min_max_cast_to_unsigned ( ints, out)
395367 } ;
396368 let ints = bytemuck:: must_cast_slice_mut ( ints) ;
397- let min_max = min_max. map ( |( min, max) | ( min. to_unsigned ( ) , max. to_unsigned ( ) ) ) ;
398369 pack_ints_sized_unsigned :: < T :: Unsigned > ( ints, out, basic_packing, min_max) ;
399370}
400371
@@ -405,24 +376,7 @@ fn pack_ints_sized_unsigned<T: SizedUInt>(
405376 basic_packing : Packing ,
406377 min_max : Option < ( T , T ) > ,
407378) {
408- let p = if let Some ( ( min, max) ) = min_max {
409- // If subtracting min from all ints results in a better packing do it, otherwise don't bother.
410- let offset_packing = Packing :: new ( max. wrapping_sub ( min) ) ;
411- if offset_packing > basic_packing && ints. len ( ) > 5 {
412- for b in ints. iter_mut ( ) {
413- * b = b. wrapping_sub ( min) ;
414- }
415- offset_packing. write :: < T > ( out, true ) ;
416- T :: write ( min, out) ;
417- offset_packing
418- } else {
419- basic_packing. write :: < T > ( out, false ) ;
420- basic_packing
421- }
422- } else {
423- basic_packing
424- } ;
425-
379+ let p = crate :: pack_shared:: offset_packing ( ints, out, basic_packing, min_max) ;
426380 match p {
427381 Packing :: _128 => T :: pack128 ( ints, out) ,
428382 Packing :: _64 => T :: pack64 ( ints, out) ,
0 commit comments