| author | |
| committer | |
| log | 13cb4951940e677dae5c012b333a73cd0a2931f8 |
| tree | 92ce791e3aa5793fb9c4cf19ca152be51df9d62a |
| parent | 030812ffcf6b49f708de116ef6c5f6fcad955b41 |
6 files changed, 165 insertions(+), 0 deletions(-)
base32.zig created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | //! https://www.crockford.com/base32.html | ||
| 2 | |||
| 3 | const std = @import("std"); | ||
| 4 | const string = []const u8; | ||
| 5 | const range = @import("range").range; | ||
| 6 | |||
| 7 | const alphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; | ||
| 8 | |||
| 9 | pub 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 | |||
| 23 | pub 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 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const deps = @import("./deps.zig"); | ||
| 3 | |||
| 4 | pub 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 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const string = []const u8; | ||
| 3 | const ulid = @import("ulid"); | ||
| 4 | |||
| 5 | pub 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 | |||
| 27 | fn 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 | |||
| 3 | const std = @import("std"); | ||
| 4 | const string = []const u8; | ||
| 5 | const base32 = @import("./base32.zig"); | ||
| 6 | const extras = @import("extras"); | ||
| 7 | |||
| 8 | pub 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 | ||
| 33 | pub 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 @@ | ||
| 1 | id: 1vu3948bgf52ytvq9u4skpj8es5hd30s0tfx2f15hjaa4tnl | ||
| 2 | name: ulid | ||
| 3 | main: ulid.zig | ||
| 4 | license: MIT | ||
| 5 | description: ULID implementation for Zig | ||
| 6 | dependencies: | ||
| 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 @@ | ||
| 1 | 2 | ||
| 2 | git https://github.com/nektro/zig-range commit-890ca308fe09b3d5c866d5cfb3b3d7a95dbf939f | ||
| 3 | git https://github.com/nektro/zig-extras commit-86e312abea8012e39f868f1f2fbc72d6e28a466b | ||