Created
April 26, 2024 04:57
-
-
Save mzaks/aa66c831dc5e177c2322d5088aac76aa to your computer and use it in GitHub Desktop.
Mojo Hasher POC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Hashable: | |
fn __hash__[H: Hasher](self, inout hasher: H): | |
... | |
trait Hasher: | |
fn __init__(inout self): | |
... | |
fn update(inout self, bytes: DTypePointer[DType.uint8], n: Int): | |
... | |
fn finish[dt: DType = DType.uint64](owned self) -> Scalar[dt]: | |
... | |
@value | |
struct MyInt(Hashable): | |
var value: Int | |
fn __hash__[H: Hasher](self, inout hasher: H): | |
var i64 = Int64(self.value) | |
var p = DTypePointer.address_of(i64) | |
hasher.update(p.bitcast[DType.uint8](), 8) | |
@value | |
struct MyString(Hashable): | |
var value: StringLiteral | |
fn __hash__[H: Hasher](self, inout hasher: H): | |
MyInt(len(self.value)).__hash__(hasher) | |
hasher.update(self.value.data().bitcast[DType.uint8](), len(self.value)) | |
@value | |
struct Person(Hashable): | |
var name: MyString | |
var age: MyInt | |
fn __hash__[H: Hasher](self, inout hasher: H): | |
self.name.__hash__(hasher) | |
self.age.__hash__(hasher) | |
fn my_hash[V: Hashable, hasher_type: Hasher = DJBX33A_Hasher[0]](value: V) -> UInt64: | |
var hasher = hasher_type() | |
value.__hash__(hasher) | |
return hasher^.finish() | |
from os.env import getenv, setenv | |
from random import random_si64 | |
fn _DJBX33A_SECRET() -> UInt64: | |
try: | |
var secret_string = getenv("DJBX33A_SECRET", "") | |
return bitcast[DType.uint64](Int64(int(secret_string))) | |
except: | |
var value = random_si64(Int64.MIN, Int64.MAX) | |
_ = setenv("DJBX33A_SECRET", str(value)) | |
return bitcast[DType.uint64](value) | |
struct DJBX33A_Hasher[custom_secret: UInt64 = 0](Hasher): | |
var hash_data: UInt64 | |
var secret: UInt64 | |
fn __init__(inout self): | |
self.hash_data = 5361 | |
@parameter | |
if custom_secret != 0: | |
self.secret = custom_secret | |
else: | |
self.secret = _DJBX33A_SECRET() | |
fn update(inout self, bytes: DTypePointer[DType.uint8], n: Int): | |
for i in range(n): | |
self.hash_data = self.hash_data * 33 + bytes.load(i).cast[DType.uint64]() | |
fn finish[dt: DType = DType.uint64](owned self) -> Scalar[dt]: | |
return (self.hash_data ^ self.secret).cast[dt]() | |
fn main() raises: | |
var p = Person("Maxim", 43) | |
print(p.name.value, p.age.value) | |
var hasher = DJBX33A_Hasher() | |
p.age.__hash__(hasher) | |
print("My hasher 43", hasher^.finish()) | |
print("Std hash 43", hash(p.age.value)) | |
hasher = DJBX33A_Hasher() | |
p.__hash__(hasher) | |
print("Person", hasher^.finish()) | |
var h1 = my_hash(p) | |
var h2 = my_hash[hasher_type=DJBX33A_Hasher[77777]](p) | |
var h3 = my_hash(p) | |
print("Person", h1, h2, h3) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment