diff --git a/README.md b/README.md new file mode 100644 index 0000000..76ee9c0 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# Hash Array Mapped Trie + +A barebones implementation of [this paper](https://infoscience.epfl.ch/record/64398) by Phil Bagwell. + +### Usage + +As an example: +```zig +const std = @import("std"); +const expectEqual = std.testing.expectEqual; +const HashArrayMappedTrie = @import("hamt").HashArrayMappedTrie; + +const StringTrie = HashArrayMappedTrie([]const u8, void, StringContext); + +const StringContext = struct { + // Note: This definition is *required* + // TODO: I could just grab the @typeInfo(HashFn).Fn.return_type right? + pub const Digest = u64; + + pub inline fn hash(key: []const u8) Digest { + return std.hash.Wyhash.hash(0, key); + } + + pub inline fn eql(left: []const u8, right: []const u8) bool { + return std.mem.eql(u8, left, right); + } +}; + +test { + const Pair = StringTrie.Pair; + const allocator = std.testing.allocator; + + var trie = StringTrie.init(); + defer trie.deinit(allocator); + + try trie.insert(allocator, "hello", {}); + + try expectEqual(@as(?Pair, .{ .key = "hello", .value = {} }), trie.search("hello")); + try expectEqual(@as(?Pair, null), trie.search("world")); +} +``` + +### Building + +Build in release mode with `zig build -Doptimzie=ReleaseSafe`; + diff --git a/build.zig b/build.zig index b8263c9..9bf202b 100644 --- a/build.zig +++ b/build.zig @@ -15,6 +15,9 @@ pub fn build(b: *std.Build) void { // set a preferred release mode, allowing the user to decide how to optimize. const optimize = b.standardOptimizeOption(.{}); + const module = b.addModule("hamt", .{ .source_file = .{ .path = "src/lib.zig" } }); + _ = module; + const lib = b.addStaticLibrary(.{ .name = "hamt", // In this case the main source file is merely a path, however, in more diff --git a/build.zig.zon b/build.zig.zon index 0844498..003940b 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "SDL", - .version = "0.0.1", + .name = "hamt", + .version = "0.1.0", .dependencies = .{}, } diff --git a/src/trie.zig b/src/trie.zig index 95f8705..b127f15 100644 --- a/src/trie.zig +++ b/src/trie.zig @@ -21,7 +21,7 @@ pub fn HashArrayMappedTrie(comptime K: type, comptime V: type, comptime Context: const Node = union(enum) { kv: Pair, table: Table }; const Table = struct { map: Digest = 0, base: [*]Node }; - const Pair = struct { key: K, value: V }; + pub const Pair = struct { key: K, value: V }; pub fn init() Self { return Self{ .root = [_]?*Node{null} ** table_size }; @@ -291,23 +291,23 @@ const StringContext = struct { } }; -const TestHamt = HashArrayMappedTrie([]const u8, void, StringContext); +const StringTrie = HashArrayMappedTrie([]const u8, void, StringContext); test "trie init" { - _ = TestHamt.init(); + _ = StringTrie.init(); } test "init and deinit" { const allocator = std.testing.allocator; - var trie = TestHamt.init(); + var trie = StringTrie.init(); defer trie.deinit(allocator); } test "trie insert" { const allocator = std.testing.allocator; - var trie = TestHamt.init(); + var trie = StringTrie.init(); defer trie.deinit(allocator); try trie.insert(allocator, "hello", {}); @@ -315,10 +315,10 @@ test "trie insert" { } test "trie search" { - const Pair = TestHamt.Pair; + const Pair = StringTrie.Pair; const allocator = std.testing.allocator; - var trie = TestHamt.init(); + var trie = StringTrie.init(); defer trie.deinit(allocator); try std.testing.expectEqual(@as(?Pair, null), trie.search("sdvx")); @@ -331,3 +331,16 @@ test "trie search" { try trie.insert(allocator, "", {}); try std.testing.expectEqual(@as(?Pair, .{ .key = "", .value = {} }), trie.search("")); } + +test "README.md example" { + const Pair = StringTrie.Pair; + const allocator = std.testing.allocator; + + var trie = StringTrie.init(); + defer trie.deinit(allocator); + + try trie.insert(allocator, "hello", {}); + + try std.testing.expectEqual(@as(?Pair, .{ .key = "hello", .value = {} }), trie.search("hello")); + try std.testing.expectEqual(@as(?Pair, null), trie.search("world")); +}