Update: Now RFC-9562 compliant
zuid is a RFC-4122 compliant UUID library for Zig. It includes UUID creation for v1, v3, v4, and v5, converting UUIDs to strings, 128-bit integers, and byte arrays. It also supports creating a UUID from a string.
#ZUID
1 messages · Page 1 of 1 (latest)
There's no reason to allocate here, you can use the streaming hasher API https://github.com/KeithBrown39423/zuid/blob/main/src/zuid.zig#L165-L181
Same for v5
specifically, you create a hasher with std.crypto.hash.Md5.init(.{}) (or the equivalent for Sha1), then call hasher.update() with each section of the string that you're currently concatenating
also, bit of a nitpick but I don't think you can claim support for "all versions" without supporting v2 
It's uncommon for sure, but it is still a thing
It'd be a breaking change but I attempted to fix that issue here: https://github.com/theoparis/zuid/commit/c2331325f9f6ae3627eaecb91f8ed972a51bfed2
Not sure if I should PR due to the amount of changes zig fmt made
any zig project accepting contributions should be using zig fmt anyway imo
true
I left a comment on your pr
yeah, i forgot to run zig fmt before i pushed it. i do appreciate having zig fmt tho
i mean, i can add it, i just didnt think anyone would ever use it
If you configure your editor to fmt on save, you never have that issue :)
I agree, I'm just being picky about the wording in your readme heheh
i have autosave turned on, fmt on save would cause my computer to shit itself
yea, ill probably do that as well as adding a zig build test workflow per @humble cape's suggestion
theres also v6, v7, and v8 but there isnt too much need there
oh also, any off chance of getting the ability to swap out the time functions? thats more of a request for the zig std itself but in my osdev code i cant use the posix syscall that zig uses by default for it on nonwindows because i am the kernel
i dont really intend to use the time-based uuids for much of anything so doesnt impact me much though
my biggest thing here was there (at least from what ive seen), there is no official support for v6 v7 and v8
what would i swap the time functions out with?
idk, just the option to provide my own nanoTimestamp since std wont let me override it
and yeah thats fair, all i really know about 6 7 and 8 is they theoretically exist, ive only ever seen v4 and v5 in the wild, and even then only really v4
yeah, rfc officially supports v1 3 4 and 5, and says v2 is by someone else. v6-8 arent officially supporting by rfc yet
https://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01 heres the official spec for v2 btw
also im pretty sure if you reverse the field order you can make the uuid a packed struct(u128) and then the toInt method becomes just a @bitCast
why would I need to reverse it?
least significant bits (less shifted over) go first in packed structs
ah okay
would it be better to put the bitcast in a toInt method, your just add to some kind of documentation how to convert it to an integer
oh also for all your nativetobig(bytesToValue) stuff, std.mem.readInt exists
takes bytes and you can specify the endianness
i didnt even think about that
With the release of RFC9562. RFC4122 is now obselete. I will be posting a version 2 in the coming days implementing RFC9562
For more information, see https://www.rfc-editor.org/rfc/rfc9562.html
This specification defines UUIDs (Universally Unique IDentifiers) --
also known as GUIDs (Globally Unique IDentifiers) -- and a Uniform
Resource Name namespace for UUIDs. A UUID is 128 bits long and is intended to
guarantee uniqueness across space and time. UUIDs were originally used
in the Apollo Network Computi...
Coming days, more like now
Version 2.0.0 has been pushed. A release will be made within the hour
hell yeah
can you not bitcast to a u128 and use writeInt with .big to get the array form of the uuid?
instead of tostring-ing it
especially considering the binary size overhead of std.fmt
also i think implementing format instead of tostring is more standard for zig generally
the biggest issue with this was the -'s
I'm a bit lost with what you mean by this though
zig's std.fmt stuff looks for a function on the type of the form
pub fn format(self: *const @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void
in order to use a thing in a fmt expression
for the toArray method? the -s arent actually part of the zuid, they get added in in tostring
and then toArray skips them
whereas
pub fn toArray(self: Uuid) [16]u8 {
var byte_array: [16]u8 = undefined;
std.mem.writeInt(u128, &byte_array, @bitCast(self), .big);
return byte_array;
}
works perfect for the toArray thing
yea, I see what you mean now. I was very confused for a moment
if you want, you could make a pr :)
if not I'll add that once I get home
this would allow me to do something like std.print({s}, UUID), right?
(sorry for shitty pseudocode I'm on my phone rn)
yup, and whatever is in between the {} would get passed in as the fmt parameter in that function type
im doing the to/fromArray one now
those would allow me do specify formatting functions if they want to print it as an int without converting it
yep, or even come up with a specifier for including the surrounding {} in the uuid string as some formats and scenarios do
what I can implement custom specifiers?
yeah
I can't think of how I'd use that, but that's cool
if it gets done as writer.print("{something}", .{ uuid }); for example, then the comptime fmt: [] const u8 parameter in the format method will be the comptime string "something"
okay. I see, that's really cool
the options parameter is kind of a PITA to implement correctly though and most people ignore it
theres an open zig issue to just ditch it and implement its semantics in the root format method itself
the fill, width, alignment, etc stuff after the : in the specifier is what goes into options and doesnt get passed in the specifier string
if you want to keep toString a placeholder format could be
pub fn format(self: *const Uuid, comptime _: []const u8, _: std.fmt.FormatOptions, fmt: anytype) !void {
try fmt.writeAll(&self.toString());
}
alright i opened https://github.com/KeithBrown39423/zuid/pull/3
ah yup
my local copy has uuid by value in that function and i forgot its by pointer in the repo
yay it worked, it's been merged
cool
ive added this, although i only have s, S, and d
cool
i might add x that is the same as s just without the -
yeah thatd make sense to me
what endianess does bitCast use
no
let me rephrase that
what endian will std.debug.print("{x:0>8}\n", .{self.set_1}); this print
there is no such thing as endianness here - the bit math to get the value of a packed struct field is endian independent
all numbers are printed normally
endian only exists when you view a thing as a list of bytes
specifically packed struct fields are defined as being least to most significant bits
so the last field will have the most significant bits which would by definition be in the first byte(s) in big endian
if i pass in a number into std.fmt, what endian does it print in
there is no endianness to a raw number, its always printed in the natural (most significant digit first) order used in writing
but a number doesnt actually have endianness, a byte representation of one does
alright i updated zuid in my project and nothing broke \o/
yayy
I think the only thing that's changed with how you actually use. It is parsing it as a string.
well that and the new uuid types which i dont use
ive got v4, v5, and the nul uid so far
oh btw, since the spec defines nul and max uuids, heres a quick def for them
pub const nul: UUID = @bitCast(@as(u128, 0));
pub const max: UUID = @bitCast(@as(u128, std.math.maxInt(u128)));
It seems with zig 0.15.0 the string formatting is broken :/
edit: i'll put a pr up soon to fix it :)
const tmp_path = try std.fmt.allocPrint(app.alloc, "{s}/{s}-{s}", .{ trash_dir_path, entry.name, zuid.new.v4() });
yes it is sadly, I just haven't kept up with it
hope this helps then :)
https://github.com/KeithBrown39423/zuid/pull/4
i updated the ci workflow to use the latest zig version
@noble halo finally got around to updating this