@@ -209,10 +209,144 @@ impl<S: Sip> Hasher<S> {
209209        self . state . v3  = self . k1  ^ 0x7465646279746573 ; 
210210        self . ntail  = 0 ; 
211211    } 
212+ 
213+     // A specialized write function for values with size <= 8. 
214+     // 
215+     // The hashing of multi-byte integers depends on endianness. E.g.: 
216+     // - little-endian: `write_u32(0xDDCCBBAA)` == `write([0xAA, 0xBB, 0xCC, 0xDD])` 
217+     // - big-endian:    `write_u32(0xDDCCBBAA)` == `write([0xDD, 0xCC, 0xBB, 0xAA])` 
218+     // 
219+     // This function does the right thing for little-endian hardware. On 
220+     // big-endian hardware `x` must be byte-swapped first to give the right 
221+     // behaviour. After any byte-swapping, the input must be zero-extended to 
222+     // 64-bits. The caller is responsible for the byte-swapping and 
223+     // zero-extension. 
224+     #[ inline]  
225+     fn  short_write < T > ( & mut  self ,  _x :  T ,  x :  u64 )  { 
226+         let  size = mem:: size_of :: < T > ( ) ; 
227+         self . length  += size; 
228+ 
229+         // The original number must be zero-extended, not sign-extended. 
230+         debug_assert ! ( if  size < 8  {  x >> ( 8  *  size)  == 0  }  else {  true  } ) ; 
231+ 
232+         // The number of bytes needed to fill `self.tail`. 
233+ 
234+         let  needed = 8  - self . ntail ; 
235+ 
236+         // SipHash parses the input stream as 8-byte little-endian integers. 
237+         // Inputs are put into `self.tail` until 8 bytes of data have been 
238+         // collected, and then that word is processed. 
239+         // 
240+         // For example, imagine that `self.tail` is 0x0000_00EE_DDCC_BBAA, 
241+         // `self.ntail` is 5 (because 5 bytes have been put into `self.tail`), 
242+         // and `needed` is therefore 3. 
243+         // 
244+         // - Scenario 1, `self.write_u8(0xFF)`: we have already zero-extended 
245+         //   the input to 0x0000_0000_0000_00FF. We now left-shift it five 
246+         //   bytes, giving 0x0000_FF00_0000_0000. We then bitwise-OR that value 
247+         //   into `self.tail`, resulting in 0x0000_FFEE_DDCC_BBAA. 
248+         //   (Zero-extension of the original input is critical in this scenario 
249+         //   because we don't want the high two bytes of `self.tail` to be 
250+         //   touched by the bitwise-OR.) `self.tail` is not yet full, so we 
251+         //   return early, after updating `self.ntail` to 6. 
252+         // 
253+         // - Scenario 2, `self.write_u32(0xIIHH_GGFF)`: we have already 
254+         //   zero-extended the input to 0x0000_0000_IIHH_GGFF. We now 
255+         //   left-shift it five bytes, giving 0xHHGG_FF00_0000_0000. We then 
256+         //   bitwise-OR that value into `self.tail`, resulting in 
257+         //   0xHHGG_FFEE_DDCC_BBAA. `self.tail` is now full, and we can use it 
258+         //   to update `self.state`. (As mentioned above, this assumes a 
259+         //   little-endian machine; on a big-endian machine we would have 
260+         //   byte-swapped 0xIIHH_GGFF in the caller, giving 0xFFGG_HHII, and we 
261+         //   would then end up bitwise-ORing 0xGGHH_II00_0000_0000 into 
262+         //   `self.tail`). 
263+         // 
264+         self . tail  |= x << ( 8  *  self . ntail ) ; 
265+         if  size < needed { 
266+             self . ntail  += size; 
267+             return ; 
268+         } 
269+ 
270+         // `self.tail` is full, process it. 
271+ 
272+         self . state . v3  ^= self . tail ; 
273+         S :: c_rounds ( & mut  self . state ) ; 
274+         self . state . v0  ^= self . tail ; 
275+ 
276+         // Continuing scenario 2: we have one byte left over from the input. We 
277+         // set `self.ntail` to 1 and `self.tail` to `0x0000_0000_IIHH_GGFF >> 
278+         // 8*3`, which is 0x0000_0000_0000_00II. (Or on a big-endian machine 
279+         // the prior byte-swapping would leave us with 0x0000_0000_0000_00FF.) 
280+         // 
281+         // The `if` is needed to avoid shifting by 64 bits, which Rust 
282+         // complains about. 
283+         self . ntail  = size - needed; 
284+         self . tail  = if  needed < 8  {  x >> ( 8  *  needed)  }  else  {  0  } ; 
285+     } 
212286} 
213287
214288#[ stable( feature = "rust1" ,  since = "1.0.0" ) ]  
215289impl  super :: Hasher  for  SipHasher  { 
290+     #[ inline]  
291+     fn  write_u8 ( & mut  self ,  i :  u8 )  { 
292+         self . 0 . hasher . write_u8 ( i) ; 
293+     } 
294+ 
295+     #[ inline]  
296+     fn  write_u16 ( & mut  self ,  i :  u16 )  { 
297+         self . 0 . hasher . write_u16 ( i) ; 
298+     } 
299+ 
300+     #[ inline]  
301+     fn  write_u32 ( & mut  self ,  i :  u32 )  { 
302+         self . 0 . hasher . write_u32 ( i) ; 
303+     } 
304+ 
305+     #[ inline]  
306+     fn  write_u64 ( & mut  self ,  i :  u64 )  { 
307+         self . 0 . hasher . write_u64 ( i) ; 
308+     } 
309+ 
310+     #[ inline]  
311+     fn  write_u128 ( & mut  self ,  i :  u128 )  { 
312+         self . 0 . hasher . write_u128 ( i) ; 
313+     } 
314+ 
315+     #[ inline]  
316+     fn  write_usize ( & mut  self ,  i :  usize )  { 
317+         self . 0 . hasher . write_usize ( i) ; 
318+     } 
319+ 
320+     #[ inline]  
321+     fn  write_i8 ( & mut  self ,  i :  i8 )  { 
322+         self . 0 . hasher . write_i8 ( i) ; 
323+     } 
324+ 
325+     #[ inline]  
326+     fn  write_i16 ( & mut  self ,  i :  i16 )  { 
327+         self . 0 . hasher . write_i16 ( i) ; 
328+     } 
329+ 
330+     #[ inline]  
331+     fn  write_i32 ( & mut  self ,  i :  i32 )  { 
332+         self . 0 . hasher . write_i32 ( i) ; 
333+     } 
334+ 
335+     #[ inline]  
336+     fn  write_i64 ( & mut  self ,  i :  i64 )  { 
337+         self . 0 . hasher . write_i64 ( i) ; 
338+     } 
339+ 
340+     #[ inline]  
341+     fn  write_i128 ( & mut  self ,  i :  i128 )  { 
342+         self . 0 . hasher . write_i128 ( i) ; 
343+     } 
344+ 
345+     #[ inline]  
346+     fn  write_isize ( & mut  self ,  i :  isize )  { 
347+         self . 0 . hasher . write_isize ( i) ; 
348+     } 
349+ 
216350    #[ inline]  
217351    fn  write ( & mut  self ,  msg :  & [ u8 ] )  { 
218352        self . 0 . hasher . write ( msg) 
@@ -231,6 +365,66 @@ impl super::Hasher for SipHasher {
231365
232366#[ unstable( feature = "hashmap_internals" ,  issue = "none" ) ]  
233367impl  super :: Hasher  for  SipHasher13  { 
368+     #[ inline]  
369+     fn  write_u8 ( & mut  self ,  i :  u8 )  { 
370+         self . hasher . write_u8 ( i) ; 
371+     } 
372+ 
373+     #[ inline]  
374+     fn  write_u16 ( & mut  self ,  i :  u16 )  { 
375+         self . hasher . write_u16 ( i) ; 
376+     } 
377+ 
378+     #[ inline]  
379+     fn  write_u32 ( & mut  self ,  i :  u32 )  { 
380+         self . hasher . write_u32 ( i) ; 
381+     } 
382+ 
383+     #[ inline]  
384+     fn  write_u64 ( & mut  self ,  i :  u64 )  { 
385+         self . hasher . write_u64 ( i) ; 
386+     } 
387+ 
388+     #[ inline]  
389+     fn  write_u128 ( & mut  self ,  i :  u128 )  { 
390+         self . hasher . write_u128 ( i) ; 
391+     } 
392+ 
393+     #[ inline]  
394+     fn  write_usize ( & mut  self ,  i :  usize )  { 
395+         self . hasher . write_usize ( i) ; 
396+     } 
397+ 
398+     #[ inline]  
399+     fn  write_i8 ( & mut  self ,  i :  i8 )  { 
400+         self . hasher . write_i8 ( i) ; 
401+     } 
402+ 
403+     #[ inline]  
404+     fn  write_i16 ( & mut  self ,  i :  i16 )  { 
405+         self . hasher . write_i16 ( i) ; 
406+     } 
407+ 
408+     #[ inline]  
409+     fn  write_i32 ( & mut  self ,  i :  i32 )  { 
410+         self . hasher . write_i32 ( i) ; 
411+     } 
412+ 
413+     #[ inline]  
414+     fn  write_i64 ( & mut  self ,  i :  i64 )  { 
415+         self . hasher . write_i64 ( i) ; 
416+     } 
417+ 
418+     #[ inline]  
419+     fn  write_i128 ( & mut  self ,  i :  i128 )  { 
420+         self . hasher . write_i128 ( i) ; 
421+     } 
422+ 
423+     #[ inline]  
424+     fn  write_isize ( & mut  self ,  i :  isize )  { 
425+         self . hasher . write_isize ( i) ; 
426+     } 
427+ 
234428    #[ inline]  
235429    fn  write ( & mut  self ,  msg :  & [ u8 ] )  { 
236430        self . hasher . write ( msg) 
@@ -248,13 +442,59 @@ impl super::Hasher for SipHasher13 {
248442} 
249443
250444impl < S :  Sip >  super :: Hasher  for  Hasher < S >  { 
251-     // Note: no integer hashing methods (`write_u*`, `write_i*`) are defined 
252-     // for this type. We could add them, copy the `short_write` implementation 
253-     // in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*` 
254-     // methods to `SipHasher`, `SipHasher13`, and `DefaultHasher`. This would 
255-     // greatly speed up integer hashing by those hashers, at the cost of 
256-     // slightly slowing down compile speeds on some benchmarks. See #69152 for 
257-     // details. 
445+     #[ inline]  
446+     fn  write_u8 ( & mut  self ,  i :  u8 )  { 
447+         self . short_write ( i,  i as  u64 ) ; 
448+     } 
449+ 
450+     #[ inline]  
451+     fn  write_u16 ( & mut  self ,  i :  u16 )  { 
452+         self . short_write ( i,  i. to_le ( )  as  u64 ) ; 
453+     } 
454+ 
455+     #[ inline]  
456+     fn  write_u32 ( & mut  self ,  i :  u32 )  { 
457+         self . short_write ( i,  i. to_le ( )  as  u64 ) ; 
458+     } 
459+ 
460+     #[ inline]  
461+     fn  write_u64 ( & mut  self ,  i :  u64 )  { 
462+         self . short_write ( i,  i. to_le ( )  as  u64 ) ; 
463+     } 
464+ 
465+     // `write_u128` is currently unimplemented. 
466+ 
467+     #[ inline]  
468+     fn  write_usize ( & mut  self ,  i :  usize )  { 
469+         self . short_write ( i,  i. to_le ( )  as  u64 ) ; 
470+     } 
471+ 
472+     fn  write_i8 ( & mut  self ,  i :  i8 )  { 
473+         self . short_write ( i,  i as  u8  as  u64 ) ; 
474+     } 
475+ 
476+     #[ inline]  
477+     fn  write_i16 ( & mut  self ,  i :  i16 )  { 
478+         self . short_write ( i,  ( i as  u16 ) . to_le ( )  as  u64 ) ; 
479+     } 
480+ 
481+     #[ inline]  
482+     fn  write_i32 ( & mut  self ,  i :  i32 )  { 
483+         self . short_write ( i,  ( i as  u32 ) . to_le ( )  as  u64 ) ; 
484+     } 
485+ 
486+     #[ inline]  
487+     fn  write_i64 ( & mut  self ,  i :  i64 )  { 
488+         self . short_write ( i,  ( i as  u64 ) . to_le ( )  as  u64 ) ; 
489+     } 
490+ 
491+     // `write_i128` is currently unimplemented. 
492+ 
493+     #[ inline]  
494+     fn  write_isize ( & mut  self ,  i :  isize )  { 
495+         self . short_write ( i,  ( i as  usize ) . to_le ( )  as  u64 ) ; 
496+     } 
497+ 
258498    #[ inline]  
259499    fn  write ( & mut  self ,  msg :  & [ u8 ] )  { 
260500        let  length = msg. len ( ) ; 
0 commit comments