1
Fork 0
turbonss/src/validate.zig

77 lines
2.2 KiB
Zig

const std = @import("std");
const ascii = std.ascii;
const ErrCtx = @import("ErrCtx.zig");
pub fn downCast(comptime T: type, n: u64) error{InvalidRecord}!T {
return std.math.cast(T, n) orelse return error.InvalidRecord;
}
pub fn utf8(s: []const u8) error{InvalidRecord}!void {
if (!std.unicode.utf8ValidateSlice(s)) {
return error.InvalidRecord;
}
}
// # adduser žmogus
// adduser: To avoid problems, the username should consist only of letters,
// digits, underscores, periods, at signs and dashes, and not start with a dash
// (as defined by IEEE Std 1003.1-2001). For compatibility with Samba machine
// accounts $ is also supported at the end of the username
pub fn name(s: []const u8, err: *ErrCtx) error{InvalidRecord}!void {
if (s.len == 0)
return err.returnf("cannot be empty", .{}, error.InvalidRecord);
const c0 = s[0];
if (!(ascii.isAlNum(c0) or c0 == '_' or c0 == '.' or c0 == '@'))
return err.returnf("invalid character at position 0", .{}, error.InvalidRecord);
for (s[1..]) |c, i| {
if (!(ascii.isAlNum(c) or c == '_' or c == '.' or c == '@' or c == '-'))
return err.returnf(
"invalid character at position {d}",
.{i + 2},
error.InvalidRecord,
);
}
}
const testing = std.testing;
test "validate name" {
const examples = [_]struct {
name: []const u8,
wantErr: ?[]const u8 = null,
}{
.{
.name = "all-good",
},
.{
.name = "...",
},
.{
.name = "",
.wantErr = "cannot be empty",
},
.{
.name = "-no-start-dash",
.wantErr = "invalid character at position 0",
},
.{
.name = "Herbasž",
.wantErr = "invalid character at position 7",
},
};
for (examples) |tt| {
var err = ErrCtx{};
if (tt.wantErr) |wantErr| {
try testing.expectError(error.InvalidRecord, name(tt.name, &err));
try testing.expectEqualStrings(wantErr, err.unwrap().constSlice());
} else {
try name(tt.name, &err);
try testing.expectEqualStrings("", err.unwrap().constSlice());
}
}
}