hash256_std_hasher/
lib.rs

1// Copyright 2017, 2018 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![cfg_attr(not(feature = "std"), no_std)]
16
17#[macro_use]
18extern crate crunchy;
19
20#[cfg(feature = "std")]
21use std::hash;
22
23#[cfg(not(feature = "std"))]
24use core::hash;
25
26/// Hasher that just takes 8 bytes of the provided value.
27/// May only be used for keys which are 32 bytes.
28#[derive(Default)]
29pub struct Hash256StdHasher {
30	prefix: u64,
31}
32
33impl hash::Hasher for Hash256StdHasher {
34	#[inline]
35	fn finish(&self) -> u64 {
36		self.prefix
37	}
38
39	#[inline]
40	#[allow(unused_assignments)]
41	fn write(&mut self, bytes: &[u8]) {
42		// we get a length written first as 8 bytes (possibly 4 on 32-bit platforms?). this
43		// keeps it safe.
44		debug_assert!(bytes.len() == 4 || bytes.len() == 8 || bytes.len() == 32);
45		if bytes.len() < 32 { return }
46
47		let mut bytes_ptr = bytes.as_ptr();
48		let mut prefix_ptr = &mut self.prefix as *mut u64 as *mut u8;
49
50		unroll! {
51			for _i in 0..8 {
52				unsafe {
53					*prefix_ptr ^= (*bytes_ptr ^ *bytes_ptr.offset(8)) ^ (*bytes_ptr.offset(16) ^ *bytes_ptr.offset(24));
54					bytes_ptr = bytes_ptr.offset(1);
55					prefix_ptr = prefix_ptr.offset(1);
56				}
57			}
58		}
59	}
60}
61
62#[cfg(test)]
63mod tests {
64	use hash::Hasher;
65	use super::Hash256StdHasher;
66
67	#[test]
68	fn it_works() {
69		let mut bytes = [32u8; 32];
70		bytes[0] = 15;
71		let mut hasher = Hash256StdHasher::default();
72		hasher.write(&bytes);
73		assert_eq!(hasher.prefix, 47);
74	}
75}