1 module nxt.knuthhash64;
2 
3 @safe pure nothrow @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     @safe pure nothrow @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()
49     {
50         return _result;
51     }
52 
53 private:
54     private enum _seedValue = 3074457345618258791UL;
55     private enum _mulFactor = 3074457345618258799UL;
56     ulong _result = _seedValue;
57 }
58 
59 /** Compute knuthHash-64 of input `data`, with optional seed `seed`.
60  */
61 ulong knuthhash64Of()(scope const(ubyte)[] data, ulong seed = 0)
62 {
63     auto hash = KnuthHash64!()(seed);
64     hash.start();
65     hash.put(data);
66     return hash.get();
67 }
68 
69 /** Compute knuthHash-64 of input string `data`, with optional seed `seed`.
70  */
71 ulong knuthhash64Of()(in char[] data, ulong seed = 0)
72     @trusted
73 {
74     return knuthhash64Of(cast(ubyte[])data, seed);
75 }
76 
77 /// test simple `knuthhash64Of`
78 // unittest
79 // {
80 //     assert(knuthhash64Of("") == KnuthHash64!()._seedValue);
81 //     assert(knuthhash64Of("a") != KnuthHash64!()._seedValue);
82 //     assert(knuthhash64Of("a") != knuthhash64Of("b"));
83 // }
84 
85 // version(unittest)
86 // {
87 //     import std.digest : isDigest;
88 //     static assert(isDigest!(KnuthHash64!()));
89 // }