diff --git a/resources/multiple_elements.yml b/resources/multiple_elements.yml new file mode 100644 index 0000000..da81ab4 --- /dev/null +++ b/resources/multiple_elements.yml @@ -0,0 +1,9 @@ +elements: + - name: Example Name + bool_val: true + int_val: 0 + float_val: 3.14 + - name: Example Name 2 + bool_val: false + int_val: 120 + float_val: 56.123 \ No newline at end of file diff --git a/resources/yaml-test-suite/98YD-mixed.yml b/resources/yaml-test-suite/98YD-mixed.yml new file mode 100644 index 0000000..7986aa0 --- /dev/null +++ b/resources/yaml-test-suite/98YD-mixed.yml @@ -0,0 +1,14 @@ +elemennts: + - name: Spec Example 5.5. Comment Indicator + from: http://www.yaml.org/spec/1.2/spec.html#id2773032 + tags: spec comment empty + yaml: | + # Comment only. + tree: | + +STR + -STR + json: "" + dump: "" + bool_val: true + bool_val_b2: false + bool_val_with_spaces: true \ No newline at end of file diff --git a/resources/yaml-test-suite/98YD.yml b/resources/yaml-test-suite/98YD.yml index b5b0fcd..9d5fed6 100644 --- a/resources/yaml-test-suite/98YD.yml +++ b/resources/yaml-test-suite/98YD.yml @@ -8,4 +8,4 @@ elemennts: +STR -STR json: "" - dump: "" + dump: "" \ No newline at end of file diff --git a/src/root.zig b/src/root.zig index 7b851bb..0fca944 100644 --- a/src/root.zig +++ b/src/root.zig @@ -372,7 +372,7 @@ pub fn Ymlz(comptime Destination: type) type { fn parseStringExpression(self: *Self, raw_line: []const u8, depth: usize, is_multiline: bool) ![]const u8 { const expression = try self.parseSimpleExpression(raw_line, depth, is_multiline); - const value = self.getExpressionValue(expression); + const value = self.getExpressionValueWithTrim(expression); if (value.len == 0) return value; @@ -417,6 +417,10 @@ pub fn Ymlz(comptime Destination: type) type { return str; } + fn getExpressionValueWithTrim(self: *Self, expression: Expression) []const u8 { + return std.mem.trim(u8, self.getExpressionValue(expression), " "); + } + fn getExpressionValue(self: *Self, expression: Expression) []const u8 { _ = self; @@ -429,7 +433,7 @@ pub fn Ymlz(comptime Destination: type) type { fn parseBooleanExpression(self: *Self, raw_line: []const u8, depth: usize) !bool { const expression = try self.parseSimpleExpression(raw_line, depth, false); - const value = self.getExpressionValue(expression); + const value = self.getExpressionValueWithTrim(expression); const isBooleanTrue = std.mem.eql(u8, value, "True") or std.mem.eql(u8, value, "true") or std.mem.eql(u8, value, "On") or std.mem.eql(u8, value, "on"); @@ -448,7 +452,7 @@ pub fn Ymlz(comptime Destination: type) type { fn parseNumericExpression(self: *Self, comptime T: type, raw_line: []const u8, depth: usize) !T { const expression = try self.parseSimpleExpression(raw_line, depth, false); - const value = self.getExpressionValue(expression); + const value = self.getExpressionValueWithTrim(expression); switch (@typeInfo(T)) { .Int => { diff --git a/src/tests.zig b/src/tests.zig index 37f08ef..a62ecce 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -4,6 +4,88 @@ const expect = std.testing.expect; const Ymlz = @import("root.zig").Ymlz; +test "Multiple elements in yaml file" { + const MultiElement = struct { + name: []const u8, + bool_val: bool, + int_val: u8, + float_val: f64, + }; + + const Elements = struct { elements: []MultiElement }; + + const yml_file_location = try std.fs.cwd().realpathAlloc( + std.testing.allocator, + "./resources/multiple_elements.yml", + ); + defer std.testing.allocator.free(yml_file_location); + + var ymlz = try Ymlz(Elements).init(std.testing.allocator); + const result = try ymlz.loadFile(yml_file_location); + defer ymlz.deinit(result); + + // Ensure both elements are parsed as expected and we have 2 + try expect(result.elements.len == 2); + + // Test 1st element + try expect(result.elements[0].bool_val == true); + try expect(std.mem.eql(u8, result.elements[0].name, "Example Name")); + + // Ensure 1st element does *not* have spaces (A space is manually entered into the yaml file) + try expect(!std.mem.eql(u8, result.elements[0].name, "Example Name ")); + + // Test 2nd element + try expect(result.elements[1].bool_val == false); + try expect(std.mem.eql(u8, result.elements[1].name, "Example Name 2")); + + // Test Ints + try expect(result.elements[0].int_val == 0); + try expect(result.elements[1].int_val == 120); + + // Test floats + try expect(result.elements[0].float_val == 3.14); + try expect(result.elements[1].float_val == 56.123); +} + +test "98YD with bools" { + const Element = struct { + name: []const u8, + from: []const u8, + tags: []const u8, + yaml: []const u8, + tree: []const u8, + json: []const u8, + dump: []const u8, + bool_val: bool, + bool_val_2: bool, + bool_val_with_spaces: bool, + }; + + const Experiment = struct { + elements: []Element, + }; + + const yml_file_location = try std.fs.cwd().realpathAlloc( + std.testing.allocator, + "./resources/yaml-test-suite/98YD-mixed.yml", + ); + defer std.testing.allocator.free(yml_file_location); + + var ymlz = try Ymlz(Experiment).init(std.testing.allocator); + const result = try ymlz.loadFile(yml_file_location); + defer ymlz.deinit(result); + + const element = result.elements[0]; + + // Test booleans + try expect(element.bool_val == true); + try expect(element.bool_val_2 == false); + try expect(element.bool_val_with_spaces == true); + + try expect(std.mem.eql(u8, element.name, "Spec Example 5.5. Comment Indicator")); + try expect(element.dump.len == 0); +} + test "98YD" { const Element = struct { name: []const u8,