Simple KV store testing HashMap in Zig

Author Mitja Felicijan <mitja.felicijan@gmail.com> 2024-09-18 07:57:02 +0200
Committer Mitja Felicijan <mitja.felicijan@gmail.com> 2024-09-18 07:57:02 +0200
Commit f07957d7e4a67792af5356ea3f8c09b318283cce (patch)
-rw-r--r-- README.md 4
-rw-r--r-- zig-kv-store/Makefile 2
-rw-r--r-- zig-kv-store/main.zig 94
3 files changed, 100 insertions, 0 deletions
diff --git a/README.md b/README.md
...
7
> Check `shell.nix` to see the software and dependencies that are used
7
> Check `shell.nix` to see the software and dependencies that are used
8
> in these examples. If you use Nix just do `nix-shell shell.nix`.
8
> in these examples. If you use Nix just do `nix-shell shell.nix`.
9
  
9
  
  
10
Every test has it's own `Makefile` so please check that before you try
  
11
running it.
  
12
  
10
| Example                          | What does it do?                                               |
13
| Example                          | What does it do?                                               |
11
|----------------------------------|----------------------------------------------------------------|
14
|----------------------------------|----------------------------------------------------------------|
12
| [c-asm](./c-asm)                 | Calls a function written in ASM from C code.                   |
15
| [c-asm](./c-asm)                 | Calls a function written in ASM from C code.                   |
...
20
| [zig-x11](./zig-x11)             | Uses X11 to create a basic window without any bindings needed. |
23
| [zig-x11](./zig-x11)             | Uses X11 to create a basic window without any bindings needed. |
21
| [zig-http](./zig-http)           | Basic example of a HTTP 1.1 server without any routing etc.    |
24
| [zig-http](./zig-http)           | Basic example of a HTTP 1.1 server without any routing etc.    |
22
| [zig-x11-box](./zig-x11-box)     | Move a box around with arrow keys with Xlib and Zig.           |
25
| [zig-x11-box](./zig-x11-box)     | Move a box around with arrow keys with Xlib and Zig.           |
  
26
| [zig-kv-store](./zig-kv-store)   | Simple Key-value store that mimics memcached written in Zig.   |
diff --git a/zig-kv-store/Makefile b/zig-kv-store/Makefile
  
1
default:
  
2
	zig run main.zig -freference-trace
diff --git a/zig-kv-store/main.zig b/zig-kv-store/main.zig
  
1
// https://github.com/memcached/memcached/wiki/Commands
  
2
// https://ziglang.org/documentation/master/std/#std.hash_map.HashMap
  
3
  
  
4
const std = @import("std");
  
5
  
  
6
const Error = error{
  
7
    Failed,
  
8
    KeyNotFound,
  
9
};
  
10
  
  
11
const Store = struct {
  
12
    data: std.StringHashMap([]const u8),
  
13
  
  
14
    pub fn set(self: *Store, key: []const u8, value: []const u8) !void {
  
15
        self.data.put(key, value) catch |err| {
  
16
            std.log.err("Failed adding key `{s}` with error {}", .{ key, err });
  
17
            return error.Failed;
  
18
        };
  
19
    }
  
20
  
  
21
    pub fn get(self: *Store, key: []const u8) ![]const u8 {
  
22
        if (self.data.get(key)) |value| {
  
23
            return value;
  
24
        }
  
25
        return error.KeyNotFound;
  
26
    }
  
27
  
  
28
    pub fn del(self: *Store, key: []const u8) !void {
  
29
        if (!self.data.remove(key)) {
  
30
            std.log.err("Failed deleting key `{s}`", .{key});
  
31
            return error.KeyNotFound;
  
32
        }
  
33
    }
  
34
};
  
35
  
  
36
pub fn main() !void {
  
37
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
  
38
    defer arena.deinit();
  
39
    var allocator = arena.allocator();
  
40
  
  
41
    var store = Store{ .data = std.StringHashMap([]const u8).init(allocator) };
  
42
    defer store.data.deinit();
  
43
  
  
44
    // Setting new key.
  
45
    {
  
46
        const key = "johhny";
  
47
        try store.set(key, "blaze");
  
48
    }
  
49
  
  
50
    // Retrieving back existing key if we know it will never return an error.
  
51
    {
  
52
        const key = "johhny";
  
53
        const result = store.get(key) catch unreachable;
  
54
        std.log.info("Value: {s}", .{result});
  
55
    }
  
56
  
  
57
    // Retrieving back the value and handling errors.
  
58
    {
  
59
        const key = "unknown";
  
60
        if (store.get(key)) |val| {
  
61
            std.log.info("Value: {s}", .{val});
  
62
        } else |err| {
  
63
            std.log.err("Error: {any}", .{err});
  
64
        }
  
65
    }
  
66
  
  
67
    // Retrieving back key that does not exist and handling specific errors.
  
68
    {
  
69
        const key = "unknown";
  
70
        if (store.get(key)) |val| {
  
71
            std.log.info("Value: {s}", .{val});
  
72
        } else |err| switch (err) {
  
73
            error.KeyNotFound => {
  
74
                std.log.err("Key `{s}` was not found", .{key});
  
75
            },
  
76
        }
  
77
    }
  
78
  
  
79
    // Deleting existing key.
  
80
    {
  
81
        const key = "johhny";
  
82
        try store.del(key);
  
83
    }
  
84
  
  
85
    // Retrieving back the value and handling errors.
  
86
    {
  
87
        const key = "johnny";
  
88
        if (store.get(key)) |val| {
  
89
            std.log.info("Value: {s}", .{val});
  
90
        } else |err| {
  
91
            std.log.err("Error: {any}", .{err});
  
92
        }
  
93
    }
  
94
}