Skip to content

Instantly share code, notes, and snippets.

@mzaks
Created April 26, 2024 04:57
Show Gist options
  • Save mzaks/aa66c831dc5e177c2322d5088aac76aa to your computer and use it in GitHub Desktop.
Save mzaks/aa66c831dc5e177c2322d5088aac76aa to your computer and use it in GitHub Desktop.
Mojo Hasher POC
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