From 1a46d706b549ed3a530561a65d5de13017faa25d Mon Sep 17 00:00:00 2001 From: BitlyTwiser Date: Sat, 14 Sep 2024 14:18:34 -0700 Subject: [PATCH 1/5] Adjusting selected parsing expresions to trim white spaces before/after value to avoid errors. Adjusted and added tests --- resources/yaml-test-suite/98YD.yml | 3 ++ .../yaml-test-suite/multiple_elements.yml | 5 +++ src/root.zig | 10 ++++- src/tests.zig | 38 +++++++++++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 resources/yaml-test-suite/multiple_elements.yml diff --git a/resources/yaml-test-suite/98YD.yml b/resources/yaml-test-suite/98YD.yml index b5b0fcd..94a7c85 100644 --- a/resources/yaml-test-suite/98YD.yml +++ b/resources/yaml-test-suite/98YD.yml @@ -9,3 +9,6 @@ elemennts: -STR json: "" dump: "" + bool_val: true + bool_val_b2: false + bool_val_with_spaces: true diff --git a/resources/yaml-test-suite/multiple_elements.yml b/resources/yaml-test-suite/multiple_elements.yml new file mode 100644 index 0000000..ad954e1 --- /dev/null +++ b/resources/yaml-test-suite/multiple_elements.yml @@ -0,0 +1,5 @@ +elemennts: + - name: Example Name + bool_val: true + - name: Example Name 2 + bool_val: false \ No newline at end of file diff --git a/src/root.zig b/src/root.zig index 7b851bb..85b3c96 100644 --- a/src/root.zig +++ b/src/root.zig @@ -372,7 +372,10 @@ 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); + var value = self.getExpressionValue(expression); + + // Trim spaces to avoid errors when placing spaces after strings in the yaml + value = std.mem.trim(u8, value, " "); if (value.len == 0) return value; @@ -429,7 +432,10 @@ 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); + var value = self.getExpressionValue(expression); + + // Trim spaces to avoid errors when placing spaces after strings in the yaml + value = std.mem.trim(u8, value, " "); 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"); diff --git a/src/tests.zig b/src/tests.zig index 37f08ef..c5d3425 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -4,6 +4,36 @@ 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, + }; + + const Elements = struct { elements: []MultiElement }; + + const yml_file_location = try std.fs.cwd().realpathAlloc( + std.testing.allocator, + "./resources/yaml-test-suite/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")); + + // 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 "98YD" { const Element = struct { name: []const u8, @@ -13,6 +43,9 @@ test "98YD" { tree: []const u8, json: []const u8, dump: []const u8, + bool_val: bool, + bool_val_2: bool, + bool_val_with_spaces: bool, }; const Experiment = struct { @@ -31,6 +64,11 @@ test "98YD" { 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")); // dump: "" try expect(element.dump.len == 0); From 3aa6d788f7180ca1914d33cb9de797dc143a80f7 Mon Sep 17 00:00:00 2001 From: BitlyTwiser Date: Sun, 15 Sep 2024 08:43:45 -0700 Subject: [PATCH 2/5] Moving bools out of 98YD to avoid bloat. Adding trim to int parsing. Moving yaml tests to more canonical locations on disk. Adding floats in test --- resources/multiple_elements.yml | 9 ++++ resources/yaml-test-suite/98YD-mixed.yml | 14 ++++++ resources/yaml-test-suite/98YD.yml | 5 +- .../yaml-test-suite/multiple_elements.yml | 5 -- src/root.zig | 4 +- src/tests.zig | 47 +++++++++++++++++-- 6 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 resources/multiple_elements.yml create mode 100644 resources/yaml-test-suite/98YD-mixed.yml delete mode 100644 resources/yaml-test-suite/multiple_elements.yml 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 94a7c85..9d5fed6 100644 --- a/resources/yaml-test-suite/98YD.yml +++ b/resources/yaml-test-suite/98YD.yml @@ -8,7 +8,4 @@ elemennts: +STR -STR json: "" - dump: "" - bool_val: true - bool_val_b2: false - bool_val_with_spaces: true + dump: "" \ No newline at end of file diff --git a/resources/yaml-test-suite/multiple_elements.yml b/resources/yaml-test-suite/multiple_elements.yml deleted file mode 100644 index ad954e1..0000000 --- a/resources/yaml-test-suite/multiple_elements.yml +++ /dev/null @@ -1,5 +0,0 @@ -elemennts: - - name: Example Name - bool_val: true - - name: Example Name 2 - bool_val: false \ No newline at end of file diff --git a/src/root.zig b/src/root.zig index 85b3c96..8eb4e16 100644 --- a/src/root.zig +++ b/src/root.zig @@ -454,7 +454,9 @@ 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); + var value = self.getExpressionValue(expression); + + value = std.mem.trim(u8, value, " "); switch (@typeInfo(T)) { .Int => { diff --git a/src/tests.zig b/src/tests.zig index c5d3425..710d6d1 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -8,13 +8,15 @@ 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/yaml-test-suite/multiple_elements.yml", + "./resources/multiple_elements.yml", ); defer std.testing.allocator.free(yml_file_location); @@ -32,9 +34,17 @@ test "Multiple elements in yaml file" { // 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" { +test "98YD with bools" { const Element = struct { name: []const u8, from: []const u8, @@ -54,7 +64,7 @@ test "98YD" { const yml_file_location = try std.fs.cwd().realpathAlloc( std.testing.allocator, - "./resources/yaml-test-suite/98YD.yml", + "./resources/yaml-test-suite/98YD-mixed.yml", ); defer std.testing.allocator.free(yml_file_location); @@ -69,6 +79,37 @@ test "98YD" { 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, + from: []const u8, + tags: []const u8, + yaml: []const u8, + tree: []const u8, + json: []const u8, + dump: []const u8, + }; + + const Experiment = struct { + elements: []Element, + }; + + const yml_file_location = try std.fs.cwd().realpathAlloc( + std.testing.allocator, + "./resources/yaml-test-suite/98YD.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]; + try expect(std.mem.eql(u8, element.name, "Spec Example 5.5. Comment Indicator")); // dump: "" try expect(element.dump.len == 0); From f20a082203d2275bd8b578aae6d98be3a2b6c14c Mon Sep 17 00:00:00 2001 From: BitlyTwiser Date: Sun, 15 Sep 2024 09:45:19 -0700 Subject: [PATCH 3/5] Removing manual trim from various functions (string, int, bool) and created helper function to trim values at a higher level. Adjusted tests to specifically test spaces --- src/root.zig | 25 ++++++++++++++----------- src/tests.zig | 3 +++ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/root.zig b/src/root.zig index 8eb4e16..013d877 100644 --- a/src/root.zig +++ b/src/root.zig @@ -372,10 +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); - var value = self.getExpressionValue(expression); - - // Trim spaces to avoid errors when placing spaces after strings in the yaml - value = std.mem.trim(u8, value, " "); + const value = self.getExpressionValueWithTrim(expression); if (value.len == 0) return value; @@ -420,6 +417,17 @@ pub fn Ymlz(comptime Destination: type) type { return str; } + fn getExpressionValueWithTrim(self: *Self, expression: Expression) []const u8 { + _ = self; + + // Trim spaces from value + return std.mem.trim(u8, switch (expression.value) { + .Simple => expression.value.Simple, + .KV => expression.value.KV.value, + else => @panic("Not implemeted for " ++ @typeName(@TypeOf(expression.value))), + }, " "); + } + fn getExpressionValue(self: *Self, expression: Expression) []const u8 { _ = self; @@ -432,10 +440,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); - var value = self.getExpressionValue(expression); - - // Trim spaces to avoid errors when placing spaces after strings in the yaml - value = std.mem.trim(u8, value, " "); + 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"); @@ -454,9 +459,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); - var value = self.getExpressionValue(expression); - - value = std.mem.trim(u8, value, " "); + const value = self.getExpressionValueWithTrim(expression); switch (@typeInfo(T)) { .Int => { diff --git a/src/tests.zig b/src/tests.zig index 710d6d1..a62ecce 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -31,6 +31,9 @@ test "Multiple elements in yaml file" { 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")); From 0f622edd4e5b7f2fac95b95ca52b845bb16f2bb1 Mon Sep 17 00:00:00 2001 From: BitlyTwiser Date: Sun, 15 Sep 2024 10:21:08 -0700 Subject: [PATCH 4/5] Removing inline trim to clean up helper function --- src/root.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/root.zig b/src/root.zig index 013d877..dde6879 100644 --- a/src/root.zig +++ b/src/root.zig @@ -421,11 +421,13 @@ pub fn Ymlz(comptime Destination: type) type { _ = self; // Trim spaces from value - return std.mem.trim(u8, switch (expression.value) { + const value = switch (expression.value) { .Simple => expression.value.Simple, .KV => expression.value.KV.value, else => @panic("Not implemeted for " ++ @typeName(@TypeOf(expression.value))), - }, " "); + }; + + return std.mem.trim(u8, value, " "); } fn getExpressionValue(self: *Self, expression: Expression) []const u8 { From 2d268d48b0c480d4d97e894c3eb226e7acfc807a Mon Sep 17 00:00:00 2001 From: BitlyTwiser Date: Sun, 15 Sep 2024 10:23:20 -0700 Subject: [PATCH 5/5] Adjusting to PR feedback --- src/root.zig | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/root.zig b/src/root.zig index dde6879..0fca944 100644 --- a/src/root.zig +++ b/src/root.zig @@ -418,16 +418,7 @@ pub fn Ymlz(comptime Destination: type) type { } fn getExpressionValueWithTrim(self: *Self, expression: Expression) []const u8 { - _ = self; - - // Trim spaces from value - const value = switch (expression.value) { - .Simple => expression.value.Simple, - .KV => expression.value.KV.value, - else => @panic("Not implemeted for " ++ @typeName(@TypeOf(expression.value))), - }; - - return std.mem.trim(u8, value, " "); + return std.mem.trim(u8, self.getExpressionValue(expression), " "); } fn getExpressionValue(self: *Self, expression: Expression) []const u8 {