Created
October 17, 2022 08:20
-
-
Save sander/2bb060e25c2708a450c2a69efadbe1ee to your computer and use it in GitHub Desktop.
Cross-encoding list hashing inspired by objecthash
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
package listhash | |
enum Expr: | |
case Atom(value: Array[Byte] | String | Symbol) extends Expr | |
case Comp(value: List[Expr]) extends Expr | |
opaque type ListHash = Array[Byte] | |
/** Inspired by https://github.com/benlaurie/objecthash */ | |
def listHash: Expr => ListHash = | |
case Expr.Atom(a: Array[Byte]) => hash('b', a) | |
case Expr.Atom(a: String) => hash('t', encode(a)) | |
case Expr.Atom(a: Symbol) => hash('s', encode(a.name)) | |
case Expr.Comp(Nil) => hash('n') | |
case Expr.Comp(h :: t) => hash('p', listHash(h), listHash(Expr.Comp(t))) | |
/** Concatenates all input bytes and creates a SHA-256 hash */ | |
private def hash(tag: Byte, values: Array[Byte]*) = | |
val d = java.security.MessageDigest.getInstance("SHA-256") | |
d.update(tag) | |
for (v <- values) d.update(v) | |
d.digest() | |
private def encode(s: String) = s.getBytes("UTF-8") | |
@main def demo = | |
println(listHash(Expr.Comp(List.empty))) | |
println(listHash(Expr.Atom(Symbol("hello")))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment