authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2021-10-07 19:34:22 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2021-10-07 19:34:22 -07:00
log13cb4951940e677dae5c012b333a73cd0a2931f8
tree92ce791e3aa5793fb9c4cf19ca152be51df9d62a
parent030812ffcf6b49f708de116ef6c5f6fcad955b41

add code initial imlplementation


6 files changed, 165 insertions(+), 0 deletions(-)

base32.zig created+37
......@@ -0,0 +1,37 @@
1//! https://www.crockford.com/base32.html
2
3const std = @import("std");
4const string = []const u8;
5const range = @import("range").range;
6
7const alphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
8
9pub fn decode(alloc: *std.mem.Allocator, input: string) ![]const u5 {
10 const list = &std.ArrayList(u5).init(alloc);
11 defer list.deinit();
12
13 for (input) |c| {
14 for (alphabet) |d, i| {
15 if (c == d) {
16 try list.append(@intCast(u5, i));
17 }
18 }
19 }
20 return list.toOwnedSlice();
21}
22
23pub fn formatInt(comptime T: type, n: T, buf: []u8) void {
24 const l = @intCast(T, alphabet.len);
25 var x = n;
26 var i = buf.len;
27 for (range(i)) |_, j| {
28 buf[j] = alphabet[0];
29 }
30 while (true) {
31 const a = @intCast(usize, x % l);
32 x = x / l;
33 buf[i - 1] = alphabet[a];
34 i -= 1;
35 if (x == 0) break;
36 }
37}
build.zig created+23
......@@ -0,0 +1,23 @@
1const std = @import("std");
2const deps = @import("./deps.zig");
3
4pub fn build(b: *std.build.Builder) void {
5 const target = b.standardTargetOptions(.{});
6
7 const mode = b.standardReleaseOptions();
8
9 const exe = b.addExecutable("zig-ulid", "main.zig");
10 exe.setTarget(target);
11 exe.setBuildMode(mode);
12 deps.addAllTo(exe);
13 exe.install();
14
15 const run_cmd = exe.run();
16 run_cmd.step.dependOn(b.getInstallStep());
17 if (b.args) |args| {
18 run_cmd.addArgs(args);
19 }
20
21 const run_step = b.step("run", "Run the app");
22 run_step.dependOn(&run_cmd.step);
23}
main.zig created+32
......@@ -0,0 +1,32 @@
1const std = @import("std");
2const string = []const u8;
3const ulid = @import("ulid");
4
5pub fn main() anyerror!void {
6 std.log.info("All your codebase are belong to us.", .{});
7
8 try ensureFromTo("001HX7QW7K2PP61CS28B4YF00X");
9 try ensureFromTo("0015KMZ1NDDFP4WRWSVA31N0CD");
10 try ensureFromTo("0015MFYM13K180VCNCACTFRJAB");
11 try ensureFromTo("0015RMHR0WVSCBE4CJWKPCC4GJ");
12 try ensureFromTo("0017NSY29QD0YYPB0H0W5GQJQX");
13 try ensureFromTo("0017TZRGVZYHK9C26FK5AP3HTG");
14 try ensureFromTo("0017Y302CVXHJABSPHNNEBE0R7");
15 try ensureFromTo("00183KTME6PJZ773Q9A1BWFJ3X");
16 try ensureFromTo("0018ZPQ92P0NDDKNVB3PBW7D18");
17 try ensureFromTo("00193A6YMTQR01XTY757XRRJKE");
18 try ensureFromTo("0019ABB5M0YK71B4ATA90A8F81");
19 try ensureFromTo("0019GFR7YK5HNTFPS2BAQNG0PX");
20 try ensureFromTo("001A2YPKW942R97BXRAJG2BD7S");
21 try ensureFromTo("001C38D808VW1EG3JS6XJHT4EQ");
22 try ensureFromTo("001C9DSQ8SC6SVEVHFK09XBFTC");
23 try ensureFromTo("001DEJXKVPDV7BZT1Q80ZEN2PF");
24 try ensureFromTo("001F1Z79BCKADWYPDCMZ8B8G0G");
25}
26
27fn ensureFromTo(before: string) !void {
28 const alloc = std.heap.page_allocator;
29 const ul = try ulid.ULID.fromString(alloc, before);
30 const after = try ul.toString(alloc);
31 try std.testing.expectEqualStrings(before, after);
32}
ulid.zig created+62
......@@ -0,0 +1,62 @@
1//! https://github.com/ulid/spec
2
3const std = @import("std");
4const string = []const u8;
5const base32 = @import("./base32.zig");
6const extras = @import("extras");
7
8pub const Factory = struct {
9 epoch: i64,
10 rand: *std.rand.Random,
11
12 pub fn init(epoch: i64, rand: *std.rand.Random) Factory {
13 return Factory{
14 .epoch = epoch,
15 .rand = rand,
16 };
17 }
18
19 pub fn newULID(self: Factory) ULID {
20 const now = std.time.milliTimestamp();
21 return ULID{
22 .timestamp = std.math.cast(u48, now - self.epoch) catch @panic("time.milliTimestamp() is higher than 281474976710655"),
23 .randomnes = self.rand.int(u80),
24 };
25 }
26};
27
28/// 01AN4Z07BY 79KA1307SR9X4MV3
29///
30/// |----------| |----------------|
31/// Timestamp Randomness
32/// 48bits 80bits
33pub const ULID = struct {
34 timestamp: u48,
35 randomnes: u80,
36
37 pub const BaseType = string;
38
39 pub fn readField(alloc: *std.mem.Allocator, value: BaseType) !ULID {
40 if (value.len != 26) return error.Ulid;
41 return ULID{
42 .timestamp = try std.math.cast(u48, try extras.sliceToInt(u50, u5, try base32.decode(alloc, value[0..10]))),
43 .randomnes = try extras.sliceToInt(u80, u5, try base32.decode(alloc, value[10..26])),
44 };
45 }
46
47 pub fn bindField(self: ULID, alloc: *std.mem.Allocator) !BaseType {
48 var res = try alloc.alloc(u8, 26);
49 base32.formatInt(u48, self.timestamp, res[0..10]);
50 base32.formatInt(u80, self.randomnes, res[10..26]);
51 return res;
52 }
53
54 pub const fromString = readField;
55 pub const toString = bindField;
56
57 pub fn format(self: ULID, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) @TypeOf(writer).Error!void {
58 _ = fmt;
59 _ = options;
60 try writer.writeAll(self.toString());
61 }
62};
zig.mod created+8
......@@ -0,0 +1,8 @@
1id: 1vu3948bgf52ytvq9u4skpj8es5hd30s0tfx2f15hjaa4tnl
2name: ulid
3main: ulid.zig
4license: MIT
5description: ULID implementation for Zig
6dependencies:
7 - src: git https://github.com/nektro/zig-range
8 - src: git https://github.com/nektro/zig-extras
zigmod.lock created+3
......@@ -0,0 +1,3 @@
12
2git https://github.com/nektro/zig-range commit-890ca308fe09b3d5c866d5cfb3b3d7a95dbf939f
3git https://github.com/nektro/zig-extras commit-86e312abea8012e39f868f1f2fbc72d6e28a466b