diff --git a/.gitignore b/.gitignore index 03299ae..8e179b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,22 @@ -/zig-cache/ +# This file is for zig-specific build artifacts. +# If you have OS-specific or editor-specific files to ignore, +# such as *.swp or .DS_Store, put those in your global +# ~/.gitignore and put this in your ~/.gitconfig: +# +# [core] +# excludesfile = ~/.gitignore +# +# Cheers! +# -andrewrk + +.zig-cache/ +zig-out/ +/release/ +/debug/ +/build/ +/build-*/ +/docgen_tmp/ + +# Although this was renamed to .zig-cache, let's leave it here for a few +# releases to make it less annoying to work with multiple branches. +zig-cache/ \ No newline at end of file diff --git a/uuid.zig b/uuid.zig index 09c6af0..7e3ed5f 100644 --- a/uuid.zig +++ b/uuid.zig @@ -4,6 +4,8 @@ const std = @import("std"); const crypto = std.crypto; const fmt = std.fmt; +const json = std.json; +const Allocator = std.mem.Allocator; const testing = std.testing; pub const Error = error{InvalidUUID}; @@ -22,9 +24,9 @@ pub const UUID = struct { return uuid; } - fn to_string(self: UUID,slice: []u8) void { - var string:[36]u8 = format_uuid(self); - std.mem.copy(u8, slice, &string); + fn to_string(self: UUID, slice: []u8) void { + var string: [36]u8 = format_uuid(self); + std.mem.copyForwards(u8, slice, &string); } fn format_uuid(self: UUID) [36]u8 { @@ -114,6 +116,23 @@ pub const UUID = struct { return uuid; } + + pub fn jsonStringify(self: UUID, out: anytype) !void { + return out.print("\"{s}\"", .{self.format_uuid()}); + } + + pub fn jsonParse( + allocator: Allocator, + source: anytype, + _: json.ParseOptions, + ) !UUID { + switch (try source.nextAlloc(allocator, .alloc_if_needed)) { + .string, .allocated_string => |value| { + return parse(value) catch error.InvalidCharacter; + }, + else => return error.UnexpectedToken, + } + } }; // Zero UUID @@ -166,3 +185,43 @@ test "check to_string works" { std.debug.print("Second call to_string {s} \n", .{string2}); try testing.expectEqual(string1, string2); } + +test "jsonStringify" { + const uuid = UUID{ + .bytes = [_]u8{ 0x12, 0x34, 0x56, 0x78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + }; + const T = struct { id: UUID }; + const res = try json.stringifyAlloc(testing.allocator, T{ + .id = uuid, + }, .{}); + defer testing.allocator.free(res); + try testing.expectEqualStrings("{\"id\":\"12345678-0000-0000-0000-000000000000\"}", res); + + const res2 = try json.stringifyAlloc(testing.allocator, uuid, .{}); + defer testing.allocator.free(res2); + try testing.expectEqualStrings("\"12345678-0000-0000-0000-000000000000\"", res2); +} + +test "jsonParse" { + const T = struct { id: UUID }; + + const res = try json.parseFromSlice( + T, + testing.allocator, + "{\"id\": \"12345678-0000-0000-0000-000000000000\"}", + .{}, + ); + defer res.deinit(); + try testing.expectEqual([_]u8{ 0x12, 0x34, 0x56, 0x78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, res.value.id.bytes); +} + +test "bad jsonParse" { + const T = struct { id: UUID }; + + try testing.expectError(error.UnexpectedToken, json.parseFromSlice( + T, + testing.allocator, + "{\"id\": 123123}", + .{}, + )); +}