1 module nxt.knuthhash64;
2 
3 pure nothrow @safe @nogc:
4 
5 /** Knuth hash.
6  *
7  * See_Also: https://stackoverflow.com/a/9545731/683710
8  */
9 struct KnuthHash64()			// dummy templatized to prevent instantiation
10 {
11 	pure nothrow @safe @nogc:
12 
13 	pragma(msg, "WARNING: this hash really sucks collisionwise and should not be used in production!");
14 
15 	/** (Re)initialize.
16 	 */
17 	void start()
18 	{
19 		_result = _seedValue;
20 	}
21 
22 	/** Use this to feed the hash with `data`.
23 	 *
24 	 * Also implements the $(XREF range, OutputRange) interface for $(D ubyte)
25 	 * and $(D const(ubyte)[]).
26 	 */
27 	void put(scope const(ubyte)[] data...) @trusted
28 	{
29 		foreach (elt; data)
30 		{
31 			_result += elt;
32 			_result *= _mulFactor;
33 		}
34 	}
35 
36 	/** Returns: the finished hash.
37 	 *
38 	 * This also calls $(LREF start) to reset the internal _state.
39 	 */
40 	ubyte[8] finish() @trusted
41 	{
42 		version (D_Coverage) {} else pragma(inline, true);
43 		typeof(return) bytes = (cast(ubyte*)&_result)[0 .. typeof(return).sizeof];
44 		start();
45 		return bytes;
46 	}
47 
48 	ulong get() => _result;
49 
50 private:
51 	private enum _seedValue = 3074457345618258791UL;
52 	private enum _mulFactor = 3074457345618258799UL;
53 	ulong _result = _seedValue;
54 }
55 
56 /** Compute knuthHash-64 of input `data`, with optional seed `seed`.
57  */
58 ulong knuthhash64Of()(scope const(ubyte)[] data, ulong seed = 0)
59 {
60 	auto hash = KnuthHash64!()(seed);
61 	hash.start();
62 	hash.put(data);
63 	return hash.get();
64 }
65 
66 /** Compute knuthHash-64 of input string `data`, with optional seed `seed`.
67  */
68 ulong knuthhash64Of()(in char[] data, ulong seed = 0)
69 	=> knuthhash64Of(cast(ubyte[])data, seed);
70 
71 /// test simple `knuthhash64Of`
72 // unittest
73 // {
74 //	 assert(knuthhash64Of("") == KnuthHash64!()._seedValue);
75 //	 assert(knuthhash64Of("a") != KnuthHash64!()._seedValue);
76 //	 assert(knuthhash64Of("a") != knuthhash64Of("b"));
77 // }
78 
79 // version (unittest)
80 // {
81 //	 import std.digest : isDigest;
82 //	 static assert(isDigest!(KnuthHash64!()));
83 // }