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 // }