Skip to content

Support bools and enums #89

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/Yaml.zig
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ fn parseValue(self: Yaml, arena: Allocator, comptime T: type, value: Value) Erro
.float => self.parseFloat(T, value),
.@"struct" => self.parseStruct(arena, T, try value.asMap()),
.@"union" => self.parseUnion(arena, T, value),
.@"enum" => std.meta.stringToEnum(T, try value.asScalar()) orelse Error.EnumTagMissing,
.array => self.parseArray(arena, T, try value.asList()),
.pointer => if (value.asList()) |list| {
return self.parsePointer(arena, T, .{ .list = list });
Expand Down Expand Up @@ -258,6 +259,7 @@ pub const Error = error{
Unimplemented,
TypeMismatch,
StructFieldMissing,
EnumTagMissing,
ArraySizeMismatch,
UntaggedUnion,
UnionTagMissing,
Expand Down Expand Up @@ -535,6 +537,10 @@ pub const Value = union(enum) {
.float,
=> return Value{ .scalar = try std.fmt.allocPrint(arena, "{d}", .{input}) },

// TODO - Support per-field option to use yes/no or on/off instead of true/false
.bool,
=> return Value{ .scalar = try std.fmt.allocPrint(arena, "{}", .{input}) },

.@"struct" => |info| if (info.is_tuple) {
var list: std.ArrayListUnmanaged(Value) = .empty;
try list.ensureTotalCapacityPrecise(arena, info.fields.len);
Expand Down Expand Up @@ -568,6 +574,8 @@ pub const Value = union(enum) {
} else unreachable;
} else return error.UntaggedUnion,

.@"enum" => return try encode(arena, @tagName(input)),

.array => return encode(arena, &input),

.pointer => |info| switch (info.size) {
Expand Down
81 changes: 81 additions & 0 deletions src/Yaml/test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,76 @@ test "several integer bases" {
try testing.expectEqualSlices(i8, &[_]i8{ 10, -10, 16, -16, 8, -8 }, &arr);
}

test "bools" {
const source =
\\- false
\\- true
\\- off
\\- on
\\- no
\\- yes
\\- n
\\- y
;

var yaml: Yaml = .{ .source = source };
defer yaml.deinit(testing.allocator);
try yaml.load(testing.allocator);

try testing.expectEqual(yaml.docs.items.len, 1);

var arena = Arena.init(testing.allocator);
defer arena.deinit();

const arr = try yaml.parse(arena.allocator(), [8]bool);
try testing.expectEqualSlices(bool, &[_]bool{ false, true, false, true, false, true, false, true, }, &arr);
}

const TestEnum = enum {
alpha,
bravo,
charlie,
};

test "enums" {
const source =
\\- alpha
\\- bravo
\\- charlie
;

var yaml: Yaml = .{ .source = source };
defer yaml.deinit(testing.allocator);
try yaml.load(testing.allocator);

try testing.expectEqual(yaml.docs.items.len, 1);

var arena = Arena.init(testing.allocator);
defer arena.deinit();

const arr = try yaml.parse(arena.allocator(), [3]TestEnum);
try testing.expectEqualSlices(TestEnum, &[_]TestEnum{ .alpha, .bravo, .charlie }, &arr);
}

test "invalid enum" {
const source =
\\- delta
\\- echo
;

var yaml: Yaml = .{ .source = source };
defer yaml.deinit(testing.allocator);
try yaml.load(testing.allocator);

try testing.expectEqual(yaml.docs.items.len, 1);

var arena = Arena.init(testing.allocator);
defer arena.deinit();

const result = yaml.parse(arena.allocator(), [2]TestEnum);
try testing.expectError(Yaml.Error.EnumTagMissing, result);
}

test "simple map untyped" {
const source =
\\a: 0
Expand Down Expand Up @@ -641,3 +711,14 @@ test "stringify a list" {
const arr: [3]i64 = .{ 1, 2, 3 };
try testStringify("[ 1, 2, 3 ]", arr);
}

test "stringify a bool" {
try testStringify("false", false);
try testStringify("true", true);
}

test "stringify an enum" {
try testStringify("alpha", TestEnum.alpha);
try testStringify("bravo", TestEnum.bravo);
try testStringify("charlie", TestEnum.charlie);
}