difftastic/vendored_parsers/tree-sitter-hare/example/fnv.ha

180 lines
4.2 KiB
Plaintext

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// Implements the FowlerNollVo (FNV) hash function. This hash is recommended
// for hash map keys and similar applications. It is a non-cryptographic hash.
use endian;
use hash;
use io;
use strings;
def prime32: u32 = 16777619;
def prime64: u64 = 1099511628211;
def basis32: u32 = 2166136261;
def basis64: u64 = 14695981039346656037;
type state32 = struct {
hash: hash::hash,
v: u32,
};
type state64 = struct {
hash: hash::hash,
v: u64,
};
// Creates a [hash::hash] which computes the FNV-1 32-bit hash function.
//
// Unless you have a reason to use this, [fnv32a] is recommended instead.
export fn fnv32() *hash::hash = alloc(state32 {
hash = hash::hash {
stream = io::stream {
writer = &fnv32_write,
closer = &fnv_close,
},
sum = &fnv32_sum,
reset = &fnv32_reset,
sz = 4,
},
v = basis32,
}): *hash::hash;
// Creates a [hash::hash] which computes the FNV-1a 32-bit hash function.
export fn fnv32a() *hash::hash = alloc(state32 {
hash = hash::hash {
stream = io::stream {
writer = &fnv32a_write,
closer = &fnv_close,
},
sum = &fnv32_sum,
reset = &fnv32_reset,
sz = 4,
},
v = basis32,
}): *hash::hash;
// Creates a [hash::hash] which computes the FNV-1 64-bit hash function.
//
// Unless you have a reason to use this, [fnv64a] is recommended instead.
export fn fnv64() *hash::hash = alloc(state64 {
hash = hash::hash {
stream = io::stream {
writer = &fnv64_write,
closer = &fnv_close,
},
sum = &fnv64_sum,
reset = &fnv64_reset,
sz = 8,
},
v = basis64,
}): *hash::hash;
// Creates a [hash::hash] which computes the FNV-1a 64-bit hash function.
export fn fnv64a() *hash::hash = alloc(state64 {
hash = hash::hash {
stream = io::stream {
writer = &fnv64a_write,
closer = &fnv_close,
},
sum = &fnv64_sum,
reset = &fnv64_reset,
sz = 8,
},
v = basis64,
}): *hash::hash;
fn fnv_close(s: *io::stream) void = free(s);
fn fnv32_write(s: *io::stream, buf: const []u8) (size | io::error) = {
let s = s: *state32;
for (let i = 0z; i < len(buf); i += 1) {
s.v *= prime32;
s.v ^= buf[i];
};
return len(buf);
};
fn fnv32a_write(s: *io::stream, buf: const []u8) (size | io::error) = {
let s = s: *state32;
for (let i = 0z; i < len(buf); i += 1) {
s.v ^= buf[i];
s.v *= prime32;
};
return len(buf);
};
fn fnv32_reset(h: *hash::hash) void = {
let h = h: *state32;
h.v = basis32;
};
fn fnv32_sum(h: *hash::hash) []u8 = {
let h = h: *state32;
let buf: [4]u8 = [0...];
endian::host.putu32(buf, h.v);
return alloc(buf);
};
fn fnv64_write(s: *io::stream, buf: const []u8) (size | io::error) = {
let s = s: *state64;
for (let i = 0z; i < len(buf); i += 1) {
s.v *= prime64;
s.v ^= buf[i];
};
return len(buf);
};
fn fnv64a_write(s: *io::stream, buf: const []u8) (size | io::error) = {
let s = s: *state64;
for (let i = 0z; i < len(buf); i += 1) {
s.v ^= buf[i];
s.v *= prime64;
};
return len(buf);
};
fn fnv64_reset(h: *hash::hash) void = {
let h = h: *state64;
h.v = basis64;
};
fn fnv64_sum(h: *hash::hash) []u8 = {
let h = h: *state64;
let buf: [8]u8 = [0...];
endian::host.putu64(buf, h.v);
return alloc(buf);
};
// Returns the sum of a 32-bit FNV hash.
export fn sum32(h: *hash::hash) u32 = {
assert(h.reset == &fnv32_reset);
let h = h: *state32;
return h.v;
};
// Returns the sum of a 64-bit FNV hash.
export fn sum64(h: *hash::hash) u64 = {
assert(h.reset == &fnv64_reset);
let h = h: *state64;
return h.v;
};
@test fn fnv32() void = {
// TODO: Expand these tests
// I am too tired
const vectors: [_](str, u32) = [
("", 2166136261),
("hello world", 1418570095),
("Hare is a cool language", 2663852071),
("'UNIX was not designed to stop its users from doing stupid things, as that would also stop them from doing clever things' - Doug Gwyn", 1203174417),
("'Life is too short to run proprietary software' - Bdale Garbee", 493463614),
("'The central enemy of reliability is complexity.' - Geer et al", 3263526736),
("'A language that doesnt have everything is actually easier to program in than some that do.' - Dennis Ritchie", 3069348265),
];
let hash = fnv32();
defer hash::close(hash);
for (let i = 0z; i < len(vectors); i += 1) {
let vec = vectors[i];
hash::reset(hash);
hash::write(hash, strings::toutf8(vec.0));
assert(sum32(hash) == vec.1);
};
};