Create util.zig
This commit is contained in:
parent
47353aaf13
commit
5eaed13f7a
3 changed files with 133 additions and 127 deletions
|
@ -1,5 +1,5 @@
|
||||||
const root = @import("root");
|
const root = @import("root");
|
||||||
const Uuid = root.Uuid;
|
const Uuid = root.util.Uuid;
|
||||||
|
|
||||||
pub const Actor = struct {
|
pub const Actor = struct {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
|
|
131
src/main.zig
131
src/main.zig
|
@ -1,136 +1,15 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const db = @import("./db.zig");
|
|
||||||
|
pub const db = @import("./db.zig");
|
||||||
|
pub const util = @import("./util.zig");
|
||||||
|
|
||||||
pub const io_mode = .evented;
|
pub const io_mode = .evented;
|
||||||
|
|
||||||
|
const Uuid = util.Uuid;
|
||||||
|
const ciutf8 = util.ciutf8;
|
||||||
const Reader = std.net.Stream.Reader;
|
const Reader = std.net.Stream.Reader;
|
||||||
const Writer = std.net.Stream.Writer;
|
const Writer = std.net.Stream.Writer;
|
||||||
|
|
||||||
pub const Uuid = struct {
|
|
||||||
data: [16]u8,
|
|
||||||
|
|
||||||
pub fn eql(lhs: Uuid, rhs: Uuid) bool {
|
|
||||||
return std.mem.eql(u8, &lhs.data, &rhs.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn format(value: Uuid, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
|
|
||||||
try std.fmt.format(writer, "{x:0>2}{x:0>2}{x:0>2}{x:0>2}-{x:0>2}{x:0>2}-{x:0>2}{x:0>2}-{x:0>2}{x:0>2}-{x:0>2}{x:0>2}{x:0>2}{x:0>2}{x:0>2}{x:0>2}", .{
|
|
||||||
value.data[0],
|
|
||||||
value.data[1],
|
|
||||||
value.data[2],
|
|
||||||
value.data[3],
|
|
||||||
value.data[4],
|
|
||||||
value.data[5],
|
|
||||||
value.data[6],
|
|
||||||
value.data[7],
|
|
||||||
value.data[8],
|
|
||||||
value.data[9],
|
|
||||||
value.data[10],
|
|
||||||
value.data[11],
|
|
||||||
value.data[12],
|
|
||||||
value.data[13],
|
|
||||||
value.data[14],
|
|
||||||
value.data[15],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const ParseError = error{
|
|
||||||
InvalidCharacter,
|
|
||||||
};
|
|
||||||
pub fn parse(str: []const u8) ParseError!Uuid {
|
|
||||||
if (str.len < 36) return error.InvalidCharacter;
|
|
||||||
|
|
||||||
var uuid: Uuid = undefined;
|
|
||||||
var str_i: usize = 0;
|
|
||||||
var i: usize = 0;
|
|
||||||
while (i < 16 and str_i < str.len) : ({
|
|
||||||
i += 1;
|
|
||||||
str_i += 2;
|
|
||||||
}) {
|
|
||||||
uuid.data[i] = std.fmt.parseInt(u8, str[str_i .. str_i + 2], 16) catch |err| switch (err) {
|
|
||||||
error.InvalidCharacter => return error.InvalidCharacter,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (i == 3 or i == 5 or i == 7 or i == 9) {
|
|
||||||
if (str[str_i + 2] != '-') return error.InvalidCharacter;
|
|
||||||
str_i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const ciutf8 = struct {
|
|
||||||
const Hash = std.hash.Wyhash;
|
|
||||||
const View = std.unicode.Utf8View;
|
|
||||||
const toLower = std.ascii.toLower;
|
|
||||||
const isAscii = std.ascii.isASCII;
|
|
||||||
const seed = 1;
|
|
||||||
|
|
||||||
pub fn hash(str: []const u8) u64 {
|
|
||||||
// fallback to regular hash on invalid utf8
|
|
||||||
const view = View.init(str) catch return Hash.hash(seed, str);
|
|
||||||
var iter = view.iterator();
|
|
||||||
|
|
||||||
var h = Hash.init(seed);
|
|
||||||
|
|
||||||
var it = iter.nextCodepointSlice();
|
|
||||||
while (it != null) : (it = iter.nextCodepointSlice()) {
|
|
||||||
if (it.?.len == 1 and isAscii(it.?[0])) {
|
|
||||||
const ch = [1]u8{toLower(it.?[0])};
|
|
||||||
h.update(&ch);
|
|
||||||
} else {
|
|
||||||
h.update(it.?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return h.final();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn eql(a: []const u8, b: []const u8) bool {
|
|
||||||
if (a.len != b.len) return false;
|
|
||||||
|
|
||||||
const va = View.init(a) catch return std.mem.eql(u8, a, b);
|
|
||||||
const vb = View.init(b) catch return false;
|
|
||||||
|
|
||||||
var iter_a = va.iterator();
|
|
||||||
var iter_b = vb.iterator();
|
|
||||||
|
|
||||||
var it_a = iter_a.nextCodepointSlice();
|
|
||||||
var it_b = iter_b.nextCodepointSlice();
|
|
||||||
|
|
||||||
while (it_a != null and it_b != null) : ({
|
|
||||||
it_a = iter_a.nextCodepointSlice();
|
|
||||||
it_b = iter_b.nextCodepointSlice();
|
|
||||||
}) {
|
|
||||||
if (it_a.?.len != it_b.?.len) return false;
|
|
||||||
|
|
||||||
if (it_a.?.len == 1) {
|
|
||||||
if (isAscii(it_a.?[0]) and isAscii(it_b.?[0])) {
|
|
||||||
const ch_a = toLower(it_a.?[0]);
|
|
||||||
const ch_b = toLower(it_b.?[0]);
|
|
||||||
|
|
||||||
if (ch_a != ch_b) return false;
|
|
||||||
} else if (it_a.?[0] != it_b.?[0]) return false;
|
|
||||||
} else if (!std.mem.eql(u8, it_a.?, it_b.?)) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return it_a == null and it_b == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn lowerInPlace(str: []u8) void {
|
|
||||||
const view = View.init(str) catch return;
|
|
||||||
|
|
||||||
var iter = view.iterator();
|
|
||||||
var it = iter.nextCodepointSlice();
|
|
||||||
while (it != null) : (it = iter.nextCodepointSlice()) {
|
|
||||||
if (isAscii(it.?[0])) it.?[0] = toLower(it.?[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const HeaderMap = std.HashMap([]const u8, []const u8, struct {
|
const HeaderMap = std.HashMap([]const u8, []const u8, struct {
|
||||||
pub fn eql(_: @This(), a: []const u8, b: []const u8) bool {
|
pub fn eql(_: @This(), a: []const u8, b: []const u8) bool {
|
||||||
return ciutf8.eql(a, b);
|
return ciutf8.eql(a, b);
|
||||||
|
|
127
src/util.zig
Normal file
127
src/util.zig
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const root = @import("root");
|
||||||
|
|
||||||
|
pub const Uuid = struct {
|
||||||
|
data: [16]u8,
|
||||||
|
|
||||||
|
pub fn eql(lhs: Uuid, rhs: Uuid) bool {
|
||||||
|
return std.mem.eql(u8, &lhs.data, &rhs.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format(value: Uuid, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
|
||||||
|
try std.fmt.format(writer, "{x:0>2}{x:0>2}{x:0>2}{x:0>2}-{x:0>2}{x:0>2}-{x:0>2}{x:0>2}-{x:0>2}{x:0>2}-{x:0>2}{x:0>2}{x:0>2}{x:0>2}{x:0>2}{x:0>2}", .{
|
||||||
|
value.data[0],
|
||||||
|
value.data[1],
|
||||||
|
value.data[2],
|
||||||
|
value.data[3],
|
||||||
|
value.data[4],
|
||||||
|
value.data[5],
|
||||||
|
value.data[6],
|
||||||
|
value.data[7],
|
||||||
|
value.data[8],
|
||||||
|
value.data[9],
|
||||||
|
value.data[10],
|
||||||
|
value.data[11],
|
||||||
|
value.data[12],
|
||||||
|
value.data[13],
|
||||||
|
value.data[14],
|
||||||
|
value.data[15],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const ParseError = error{
|
||||||
|
InvalidCharacter,
|
||||||
|
};
|
||||||
|
pub fn parse(str: []const u8) ParseError!Uuid {
|
||||||
|
if (str.len < 36) return error.InvalidCharacter;
|
||||||
|
|
||||||
|
var uuid: Uuid = undefined;
|
||||||
|
var str_i: usize = 0;
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < 16 and str_i < str.len) : ({
|
||||||
|
i += 1;
|
||||||
|
str_i += 2;
|
||||||
|
}) {
|
||||||
|
uuid.data[i] = std.fmt.parseInt(u8, str[str_i .. str_i + 2], 16) catch |err| switch (err) {
|
||||||
|
error.InvalidCharacter => return error.InvalidCharacter,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (i == 3 or i == 5 or i == 7 or i == 9) {
|
||||||
|
if (str[str_i + 2] != '-') return error.InvalidCharacter;
|
||||||
|
str_i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ciutf8 = struct {
|
||||||
|
const Hash = std.hash.Wyhash;
|
||||||
|
const View = std.unicode.Utf8View;
|
||||||
|
const toLower = std.ascii.toLower;
|
||||||
|
const isAscii = std.ascii.isASCII;
|
||||||
|
const seed = 1;
|
||||||
|
|
||||||
|
pub fn hash(str: []const u8) u64 {
|
||||||
|
// fallback to regular hash on invalid utf8
|
||||||
|
const view = View.init(str) catch return Hash.hash(seed, str);
|
||||||
|
var iter = view.iterator();
|
||||||
|
|
||||||
|
var h = Hash.init(seed);
|
||||||
|
|
||||||
|
var it = iter.nextCodepointSlice();
|
||||||
|
while (it != null) : (it = iter.nextCodepointSlice()) {
|
||||||
|
if (it.?.len == 1 and isAscii(it.?[0])) {
|
||||||
|
const ch = [1]u8{toLower(it.?[0])};
|
||||||
|
h.update(&ch);
|
||||||
|
} else {
|
||||||
|
h.update(it.?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.final();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eql(a: []const u8, b: []const u8) bool {
|
||||||
|
if (a.len != b.len) return false;
|
||||||
|
|
||||||
|
const va = View.init(a) catch return std.mem.eql(u8, a, b);
|
||||||
|
const vb = View.init(b) catch return false;
|
||||||
|
|
||||||
|
var iter_a = va.iterator();
|
||||||
|
var iter_b = vb.iterator();
|
||||||
|
|
||||||
|
var it_a = iter_a.nextCodepointSlice();
|
||||||
|
var it_b = iter_b.nextCodepointSlice();
|
||||||
|
|
||||||
|
while (it_a != null and it_b != null) : ({
|
||||||
|
it_a = iter_a.nextCodepointSlice();
|
||||||
|
it_b = iter_b.nextCodepointSlice();
|
||||||
|
}) {
|
||||||
|
if (it_a.?.len != it_b.?.len) return false;
|
||||||
|
|
||||||
|
if (it_a.?.len == 1) {
|
||||||
|
if (isAscii(it_a.?[0]) and isAscii(it_b.?[0])) {
|
||||||
|
const ch_a = toLower(it_a.?[0]);
|
||||||
|
const ch_b = toLower(it_b.?[0]);
|
||||||
|
|
||||||
|
if (ch_a != ch_b) return false;
|
||||||
|
} else if (it_a.?[0] != it_b.?[0]) return false;
|
||||||
|
} else if (!std.mem.eql(u8, it_a.?, it_b.?)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it_a == null and it_b == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lowerInPlace(str: []u8) void {
|
||||||
|
const view = View.init(str) catch return;
|
||||||
|
|
||||||
|
var iter = view.iterator();
|
||||||
|
var it = iter.nextCodepointSlice();
|
||||||
|
while (it != null) : (it = iter.nextCodepointSlice()) {
|
||||||
|
if (isAscii(it.?[0])) it.?[0] = toLower(it.?[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in a new issue