1+ use std:: mem:: MaybeUninit ;
12use std:: time:: { Duration , Instant } ;
23
34use libc:: { free, malloc, size_t} ;
@@ -1184,13 +1185,15 @@ unsafe fn finalize_dictionary(
11841185}
11851186
11861187unsafe fn ZDICT_addEntropyTablesFromBuffer_advanced (
1187- dictBuffer : * mut core :: ffi :: c_void ,
1188+ dictBuffer : & mut [ MaybeUninit < u8 > ] ,
11881189 dictContentSize : size_t ,
1189- dictBufferCapacity : size_t ,
11901190 samples : & [ u8 ] ,
11911191 samplesSizes : & [ usize ] ,
11921192 params : ZDICT_params_t ,
11931193) -> size_t {
1194+ let dictBufferCapacity = dictBuffer. len ( ) ;
1195+ let dictBuffer = dictBuffer. as_mut_ptr ( ) . cast :: < core:: ffi:: c_void > ( ) ;
1196+
11941197 let compressionLevel = if params. compressionLevel == 0 {
11951198 ZSTD_CLEVEL_DEFAULT
11961199 } else {
@@ -1212,7 +1215,7 @@ unsafe fn ZDICT_addEntropyTablesFromBuffer_advanced(
12121215 samplesSizes,
12131216 dictBuffer
12141217 . byte_add ( dictBufferCapacity)
1215- . byte_offset ( - ( dictContentSize as isize ) ) ,
1218+ . byte_sub ( dictContentSize) ,
12161219 dictContentSize,
12171220 notificationLevel,
12181221 ) ;
@@ -1226,7 +1229,7 @@ unsafe fn ZDICT_addEntropyTablesFromBuffer_advanced(
12261229 let randomID = ZSTD_XXH64 (
12271230 dictBuffer
12281231 . byte_add ( dictBufferCapacity)
1229- . byte_offset ( - ( dictContentSize as isize ) ) ,
1232+ . byte_sub ( dictContentSize) ,
12301233 dictContentSize,
12311234 0 ,
12321235 ) ;
@@ -1241,10 +1244,10 @@ unsafe fn ZDICT_addEntropyTablesFromBuffer_advanced(
12411244
12421245 if hSize. wrapping_add ( dictContentSize) < dictBufferCapacity {
12431246 core:: ptr:: copy (
1244- ( dictBuffer as * mut core :: ffi :: c_char )
1245- . add ( dictBufferCapacity)
1246- . sub ( dictContentSize) ,
1247- ( dictBuffer as * mut core :: ffi :: c_char ) . add ( hSize) ,
1247+ dictBuffer
1248+ . byte_add ( dictBufferCapacity)
1249+ . byte_sub ( dictContentSize) ,
1250+ dictBuffer. byte_add ( hSize) ,
12481251 dictContentSize,
12491252 )
12501253 }
@@ -1406,45 +1409,56 @@ fn ZDICT_trainFromBuffer_unsafe_legacy(
14061409 dictList[ 0 ] . pos = n;
14071410 dictContentSize_0 = currentSize;
14081411
1409- unsafe {
1410- if let Err ( e) = build_dictionary_content ( dictBuffer, maxDictSize, samples, & dictList) {
1411- return e. to_error_code ( ) ;
1412+ let dictBuffer = unsafe {
1413+ if dictBuffer. is_null ( ) || maxDictSize == 0 {
1414+ & mut [ ]
1415+ } else {
1416+ core:: slice:: from_raw_parts_mut ( dictBuffer. cast :: < MaybeUninit < u8 > > ( ) , maxDictSize)
14121417 }
1418+ } ;
1419+
1420+ if let Err ( e) = build_dictionary_content ( dictBuffer, samples, & dictList) {
1421+ return e. to_error_code ( ) ;
1422+ }
14131423
1424+ unsafe {
14141425 ZDICT_addEntropyTablesFromBuffer_advanced (
14151426 dictBuffer,
14161427 dictContentSize_0 as size_t ,
1417- maxDictSize,
14181428 samples,
14191429 samplesSizes,
14201430 params. zParams ,
14211431 )
14221432 }
14231433}
14241434
1425- unsafe fn build_dictionary_content (
1426- dictBuffer : * mut core:: ffi:: c_void ,
1427- maxDictSize : size_t ,
1435+ fn build_dictionary_content (
1436+ dictBuffer : & mut [ MaybeUninit < u8 > ] ,
14281437 samples : & [ u8 ] ,
14291438 dictList : & [ DictItem ] ,
14301439) -> Result < ( ) , Error > {
14311440 // convention: table[0].pos stores the number of elements
14321441 let max = dictList[ 0 ] . pos ;
14331442
1434- let mut ptr = ( dictBuffer as * mut u8 ) . add ( maxDictSize ) ;
1443+ let mut ptr = dictBuffer. len ( ) ;
14351444 for item in & dictList[ 1 ..max as usize ] {
1436- let l = item. length ;
1437- ptr = ptr. sub ( l as usize ) ;
1438- debug_assert ! ( ptr >= dictBuffer as * mut u8 ) ;
1439- if ptr < dictBuffer as * mut u8 {
1440- return Err ( Error :: GENERIC ) ; // should not happen
1441- }
1442- core:: ptr:: copy_nonoverlapping ( samples[ item. pos as usize ..] . as_ptr ( ) , ptr, l as size_t ) ;
1445+ let l = item. length as usize ;
1446+ ptr = match ptr. checked_sub ( l) {
1447+ None => return Err ( Error :: GENERIC ) , // should not happen
1448+ Some ( v) => v,
1449+ } ;
1450+
1451+ let src = uninit_slice ( & samples[ item. pos as usize ..] [ ..l] ) ;
1452+ dictBuffer[ ptr..] [ ..l] . copy_from_slice ( src) ;
14431453 }
14441454
14451455 Ok ( ( ) )
14461456}
14471457
1458+ fn uninit_slice < T > ( slice : & [ T ] ) -> & [ MaybeUninit < T > ] {
1459+ unsafe { & * ( slice as * const [ T ] as * const [ MaybeUninit < T > ] ) }
1460+ }
1461+
14481462/// Train a dictionary from an array of samples.
14491463///
14501464/// Samples must be stored concatenated in a single flat buffer `samplesBuffer`, supplied with an
@@ -1586,6 +1600,12 @@ pub unsafe extern "C" fn ZDICT_addEntropyTablesFromBuffer(
15861600 samplesSizes : * const size_t ,
15871601 nbSamples : core:: ffi:: c_uint ,
15881602) -> size_t {
1603+ let dictBuffer = if dictBuffer. is_null ( ) || dictBufferCapacity == 0 {
1604+ & mut [ ]
1605+ } else {
1606+ core:: slice:: from_raw_parts_mut ( dictBuffer. cast :: < MaybeUninit < u8 > > ( ) , dictBufferCapacity)
1607+ } ;
1608+
15891609 let samplesSizes = if samplesSizes. is_null ( ) || nbSamples == 0 {
15901610 & [ ]
15911611 } else {
@@ -1602,7 +1622,6 @@ pub unsafe extern "C" fn ZDICT_addEntropyTablesFromBuffer(
16021622 ZDICT_addEntropyTablesFromBuffer_advanced (
16031623 dictBuffer,
16041624 dictContentSize,
1605- dictBufferCapacity,
16061625 samples,
16071626 samplesSizes,
16081627 params,
0 commit comments