From 9fe1b5f224c619e8467aa813859f79e83c592751 Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Sat, 18 Jan 2025 00:20:44 +0530 Subject: [PATCH 01/10] bring previous work to zig-toml --- README.md | 4 ++ src/main.zig | 2 + src/serialize/root.zig | 133 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 src/serialize/root.zig diff --git a/README.md b/README.md index 1160efc..09d1e8a 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,10 @@ This is a top-down LL parser that parses directly into Zig structs. * [x] Mapping to optional fields * [x] Mapping to HashMaps * [ ] Serialization + * [x] Basic types like `int`s, floating points, strings, booleans etc. + * [x] Arrays + * [x] Tables + * [ ] Inline tables ## Example See [`example1.zig`](./examples/example1.zig) for the complete code that parses [`example.toml`](./examples/example1.toml) diff --git a/src/main.zig b/src/main.zig index c0880aa..ae8b2d9 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5,6 +5,7 @@ const table = @import("./table.zig"); const struct_mapping = @import("./struct_mapping.zig"); const datetime = @import("./datetime.zig"); const value = @import("./value.zig"); +const serialize = @import("serialize/root.zig"); pub const Table = table.Table; pub const Date = datetime.Date; @@ -13,6 +14,7 @@ pub const DateTime = datetime.DateTime; pub const Value = value.Value; pub const ValueList = value.ValueList; pub const HashMap = struct_mapping.HashMap; +pub const tomlize = serialize.tomlize; pub const Position = parser.Position; pub const FieldPath = []const []const u8; diff --git a/src/serialize/root.zig b/src/serialize/root.zig new file mode 100644 index 0000000..0ebffbe --- /dev/null +++ b/src/serialize/root.zig @@ -0,0 +1,133 @@ +const std = @import("std"); +const testing = std.testing; +const Allocator = std.testing.allocator; + +const MAX_FIELD_COUNT: u8 = 255; + +pub fn tomlize(allocator: std.mem.Allocator, obj: anytype, writer: anytype) !void { + try serialize_struct(allocator, obj, writer); +} + +fn serialize_struct(allocator: std.mem.Allocator, value: anytype, writer: anytype) !void { + const ttype = @TypeOf(value); + const tinfo = @typeInfo(ttype); + if (!std.mem.eql(u8, @tagName(tinfo), "Struct")) @panic("non struct type given to serialize"); + const fields = comptime get_fields(tinfo); + + comptime var i: u8 = 0; + inline while (i < fields.len) { + const field = fields.buffer[i]; + try serialize_field(allocator, @typeInfo(field.type), field.name, @field(value, field.name), writer); + _ = try writer.write("\n"); + i += 1; + } +} + +fn serialize_simple_value(allocator: std.mem.Allocator, t: std.builtin.Type, value: anytype, writer: anytype) !void { + switch (t) { + .Int, .Float => try writer.print("{d}", .{value}), + .Bool => if (value) try writer.print("true", .{}) else try writer.print("false", .{}), + .Pointer => { + if (t.Pointer.child == u8 and t.Pointer.size == .Slice and t.Pointer.is_const) { + var esc_string = std.ArrayList(u8).init(allocator); + defer esc_string.deinit(); + const string = value; + + var curr_pos: usize = 0; + while (curr_pos <= string.len) { + const new_pos = std.mem.indexOfAnyPos(u8, string, curr_pos, &.{ '\\', '\"' }) orelse string.len; + + if (new_pos >= curr_pos) { + try esc_string.appendSlice(string[curr_pos..new_pos]); + if (new_pos != string.len) { + try esc_string.append('\\'); + try esc_string.append(string[new_pos]); + } + curr_pos = new_pos + 1; + } + } + try writer.print("\"{s}\"", .{esc_string.items}); + } else @panic("given type is not a simple type and cannot be serialized directly"); + }, + else => @panic("given type is not a simple type and cannot be serialized directly"), + } +} + +fn serialize_field(allocator: std.mem.Allocator, t: std.builtin.Type, key: []const u8, value: anytype, writer: anytype) !void { + switch (t) { + .Int, .Float, .Bool => { + try writer.print("{s} = ", .{key}); + try serialize_simple_value(allocator, t, value, writer); + }, + .Pointer => { + try writer.print("{s} = ", .{key}); + if (t.Pointer.child == u8 and t.Pointer.size == .Slice and t.Pointer.is_const) + try serialize_simple_value(allocator, t, value, writer); + }, + .Array => { + try writer.print("{s} = [ ", .{key}); + if (t.Array.len != 0) { + var i: usize = 0; + while (i < t.Array.len - 1) { + const elm = value[i]; + try serialize_simple_value(allocator, @typeInfo(t.Array.child), elm, writer); + try writer.print(", ", .{}); + i += 1; + } + } + const elm = value[t.Array.len - 1]; + try serialize_simple_value(allocator, @typeInfo(t.Array.child), elm, writer); + try writer.print(" ]", .{}); + }, + .Struct => { + try writer.print("[{s}]\n", .{key}); + try serialize_struct(allocator, value, writer); + }, + else => {}, + } +} + +fn get_fields(tinfo: std.builtin.Type) std.BoundedArray(std.builtin.Type.StructField, MAX_FIELD_COUNT) { + comptime var field_names = std.BoundedArray(std.builtin.Type.StructField, MAX_FIELD_COUNT).init(0) catch unreachable; + comptime var i: u8 = 0; + const fields = tinfo.Struct.fields; + if (fields.len > MAX_FIELD_COUNT) @panic("struct field count exceeded MAX_FIELD_COUNT"); + inline while (i < fields.len) { + const f = fields.ptr[i]; + field_names.append(f) catch unreachable; + i += 1; + } + return field_names; +} + +test "basic test" { + const TestStruct2 = struct { + field1: i32, + }; + + const TestStruct = struct { + field1: i32, + field2: []const u8, + field3: bool, + field4: f64, + field5: [5]u8, + field6: [5][]const u8, + field7: TestStruct2, + }; + + const t = TestStruct{ + .field1 = 1024, + .field2 = "hello \" \\\" \" world", + .field3 = false, + .field4 = 3.14, + .field5 = [_]u8{ 1, 2, 3, 4, 5 }, + .field6 = [_][]const u8{ "This", "is", "a", "text", "line" }, + .field7 = .{ .field1 = 10 }, + }; + + var buf: [1024]u8 = undefined; + var stream = std.io.fixedBufferStream(&buf); + var writer = stream.writer(); + try tomlize(Allocator, t, &writer); + std.debug.print("\n{s}", .{buf}); +} From ea3bafc0aa8161854767f79d1147ce531989aac7 Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Sat, 18 Jan 2025 16:45:53 +0530 Subject: [PATCH 02/10] fix function name conventions --- src/serialize/root.zig | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/serialize/root.zig b/src/serialize/root.zig index 0ebffbe..4a882fe 100644 --- a/src/serialize/root.zig +++ b/src/serialize/root.zig @@ -5,25 +5,25 @@ const Allocator = std.testing.allocator; const MAX_FIELD_COUNT: u8 = 255; pub fn tomlize(allocator: std.mem.Allocator, obj: anytype, writer: anytype) !void { - try serialize_struct(allocator, obj, writer); + try serializeStruct(allocator, obj, writer); } -fn serialize_struct(allocator: std.mem.Allocator, value: anytype, writer: anytype) !void { +fn serializeStruct(allocator: std.mem.Allocator, value: anytype, writer: anytype) !void { const ttype = @TypeOf(value); const tinfo = @typeInfo(ttype); if (!std.mem.eql(u8, @tagName(tinfo), "Struct")) @panic("non struct type given to serialize"); - const fields = comptime get_fields(tinfo); + const fields = comptime getFields(tinfo); comptime var i: u8 = 0; inline while (i < fields.len) { const field = fields.buffer[i]; - try serialize_field(allocator, @typeInfo(field.type), field.name, @field(value, field.name), writer); + try serializeField(allocator, @typeInfo(field.type), field.name, @field(value, field.name), writer); _ = try writer.write("\n"); i += 1; } } -fn serialize_simple_value(allocator: std.mem.Allocator, t: std.builtin.Type, value: anytype, writer: anytype) !void { +fn serializeSimpleValue(allocator: std.mem.Allocator, t: std.builtin.Type, value: anytype, writer: anytype) !void { switch (t) { .Int, .Float => try writer.print("{d}", .{value}), .Bool => if (value) try writer.print("true", .{}) else try writer.print("false", .{}), @@ -53,16 +53,16 @@ fn serialize_simple_value(allocator: std.mem.Allocator, t: std.builtin.Type, val } } -fn serialize_field(allocator: std.mem.Allocator, t: std.builtin.Type, key: []const u8, value: anytype, writer: anytype) !void { +fn serializeField(allocator: std.mem.Allocator, t: std.builtin.Type, key: []const u8, value: anytype, writer: anytype) !void { switch (t) { .Int, .Float, .Bool => { try writer.print("{s} = ", .{key}); - try serialize_simple_value(allocator, t, value, writer); + try serializeSimpleValue(allocator, t, value, writer); }, .Pointer => { try writer.print("{s} = ", .{key}); if (t.Pointer.child == u8 and t.Pointer.size == .Slice and t.Pointer.is_const) - try serialize_simple_value(allocator, t, value, writer); + try serializeSimpleValue(allocator, t, value, writer); }, .Array => { try writer.print("{s} = [ ", .{key}); @@ -70,24 +70,24 @@ fn serialize_field(allocator: std.mem.Allocator, t: std.builtin.Type, key: []con var i: usize = 0; while (i < t.Array.len - 1) { const elm = value[i]; - try serialize_simple_value(allocator, @typeInfo(t.Array.child), elm, writer); + try serializeSimpleValue(allocator, @typeInfo(t.Array.child), elm, writer); try writer.print(", ", .{}); i += 1; } } const elm = value[t.Array.len - 1]; - try serialize_simple_value(allocator, @typeInfo(t.Array.child), elm, writer); + try serializeSimpleValue(allocator, @typeInfo(t.Array.child), elm, writer); try writer.print(" ]", .{}); }, .Struct => { try writer.print("[{s}]\n", .{key}); - try serialize_struct(allocator, value, writer); + try serializeStruct(allocator, value, writer); }, else => {}, } } -fn get_fields(tinfo: std.builtin.Type) std.BoundedArray(std.builtin.Type.StructField, MAX_FIELD_COUNT) { +fn getFields(tinfo: std.builtin.Type) std.BoundedArray(std.builtin.Type.StructField, MAX_FIELD_COUNT) { comptime var field_names = std.BoundedArray(std.builtin.Type.StructField, MAX_FIELD_COUNT).init(0) catch unreachable; comptime var i: u8 = 0; const fields = tinfo.Struct.fields; From 1ffa7bc72ab074464819bb6af26faec6389be1bd Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Sun, 19 Jan 2025 00:14:15 +0530 Subject: [PATCH 03/10] add serializer tests in src/tests.zig --- src/tests.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tests.zig b/src/tests.zig index 9862f71..c7d0a75 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -5,6 +5,10 @@ const struct_mapping = @import("./struct_mapping.zig"); const datetime = @import("./datetime.zig"); const Table = @import("./table.zig").Table; +comptime { + _ = @import("./serialize/root.zig"); +} + test "full" { var p = main.Parser(main.Table).init(testing.allocator); defer p.deinit(); From 842dd6fe2a009ae9236f124760bd7d41d18021b5 Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Thu, 23 Jan 2025 00:17:06 +0530 Subject: [PATCH 04/10] update to zig 0.14 latest --- src/serialize/root.zig | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/serialize/root.zig b/src/serialize/root.zig index 4a882fe..4b02227 100644 --- a/src/serialize/root.zig +++ b/src/serialize/root.zig @@ -11,7 +11,7 @@ pub fn tomlize(allocator: std.mem.Allocator, obj: anytype, writer: anytype) !voi fn serializeStruct(allocator: std.mem.Allocator, value: anytype, writer: anytype) !void { const ttype = @TypeOf(value); const tinfo = @typeInfo(ttype); - if (!std.mem.eql(u8, @tagName(tinfo), "Struct")) @panic("non struct type given to serialize"); + if (!std.mem.eql(u8, @tagName(tinfo), "struct")) @panic("non struct type given to serialize"); const fields = comptime getFields(tinfo); comptime var i: u8 = 0; @@ -25,10 +25,10 @@ fn serializeStruct(allocator: std.mem.Allocator, value: anytype, writer: anytype fn serializeSimpleValue(allocator: std.mem.Allocator, t: std.builtin.Type, value: anytype, writer: anytype) !void { switch (t) { - .Int, .Float => try writer.print("{d}", .{value}), - .Bool => if (value) try writer.print("true", .{}) else try writer.print("false", .{}), - .Pointer => { - if (t.Pointer.child == u8 and t.Pointer.size == .Slice and t.Pointer.is_const) { + .int, .float => try writer.print("{d}", .{value}), + .bool => if (value) try writer.print("true", .{}) else try writer.print("false", .{}), + .pointer => { + if (t.pointer.child == u8 and t.pointer.size == .Slice and t.pointer.is_const) { var esc_string = std.ArrayList(u8).init(allocator); defer esc_string.deinit(); const string = value; @@ -55,31 +55,31 @@ fn serializeSimpleValue(allocator: std.mem.Allocator, t: std.builtin.Type, value fn serializeField(allocator: std.mem.Allocator, t: std.builtin.Type, key: []const u8, value: anytype, writer: anytype) !void { switch (t) { - .Int, .Float, .Bool => { + .int, .float, .bool => { try writer.print("{s} = ", .{key}); try serializeSimpleValue(allocator, t, value, writer); }, - .Pointer => { + .pointer => { try writer.print("{s} = ", .{key}); - if (t.Pointer.child == u8 and t.Pointer.size == .Slice and t.Pointer.is_const) + if (t.pointer.child == u8 and t.pointer.size == .Slice and t.pointer.is_const) try serializeSimpleValue(allocator, t, value, writer); }, - .Array => { + .array => { try writer.print("{s} = [ ", .{key}); - if (t.Array.len != 0) { + if (t.array.len != 0) { var i: usize = 0; - while (i < t.Array.len - 1) { + while (i < t.array.len - 1) { const elm = value[i]; - try serializeSimpleValue(allocator, @typeInfo(t.Array.child), elm, writer); + try serializeSimpleValue(allocator, @typeInfo(t.array.child), elm, writer); try writer.print(", ", .{}); i += 1; } } - const elm = value[t.Array.len - 1]; - try serializeSimpleValue(allocator, @typeInfo(t.Array.child), elm, writer); + const elm = value[t.array.len - 1]; + try serializeSimpleValue(allocator, @typeInfo(t.array.child), elm, writer); try writer.print(" ]", .{}); }, - .Struct => { + .@"struct" => { try writer.print("[{s}]\n", .{key}); try serializeStruct(allocator, value, writer); }, @@ -90,7 +90,7 @@ fn serializeField(allocator: std.mem.Allocator, t: std.builtin.Type, key: []cons fn getFields(tinfo: std.builtin.Type) std.BoundedArray(std.builtin.Type.StructField, MAX_FIELD_COUNT) { comptime var field_names = std.BoundedArray(std.builtin.Type.StructField, MAX_FIELD_COUNT).init(0) catch unreachable; comptime var i: u8 = 0; - const fields = tinfo.Struct.fields; + const fields = tinfo.@"struct".fields; if (fields.len > MAX_FIELD_COUNT) @panic("struct field count exceeded MAX_FIELD_COUNT"); inline while (i < fields.len) { const f = fields.ptr[i]; From 3be6141c5e5bc12a6f5303c8212d545eacfe9cb3 Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Fri, 24 Jan 2025 12:52:22 +0530 Subject: [PATCH 05/10] change tomlize to serialize --- README.md | 2 +- src/serialize/root.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 09d1e8a..039dab0 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ This is a top-down LL parser that parses directly into Zig structs. * [ ] Serialization * [x] Basic types like `int`s, floating points, strings, booleans etc. * [x] Arrays - * [x] Tables + * [x] Top level tables * [ ] Inline tables ## Example diff --git a/src/serialize/root.zig b/src/serialize/root.zig index 4b02227..9bbfe9a 100644 --- a/src/serialize/root.zig +++ b/src/serialize/root.zig @@ -4,7 +4,7 @@ const Allocator = std.testing.allocator; const MAX_FIELD_COUNT: u8 = 255; -pub fn tomlize(allocator: std.mem.Allocator, obj: anytype, writer: anytype) !void { +pub fn serialize(allocator: std.mem.Allocator, obj: anytype, writer: anytype) !void { try serializeStruct(allocator, obj, writer); } From f809b744f59cd53969515ca4b7851ddf65b12bde Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Fri, 24 Jan 2025 15:21:09 +0530 Subject: [PATCH 06/10] failing test --- src/serialize/root.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serialize/root.zig b/src/serialize/root.zig index 9bbfe9a..9d54ec5 100644 --- a/src/serialize/root.zig +++ b/src/serialize/root.zig @@ -128,6 +128,6 @@ test "basic test" { var buf: [1024]u8 = undefined; var stream = std.io.fixedBufferStream(&buf); var writer = stream.writer(); - try tomlize(Allocator, t, &writer); + try serialize(Allocator, t, &writer); std.debug.print("\n{s}", .{buf}); } From 3176465428b4290d254d66bd9d2d1707b08e3286 Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Fri, 24 Jan 2025 15:24:57 +0530 Subject: [PATCH 07/10] refactor while loop in serializeStruct --- src/serialize/root.zig | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/serialize/root.zig b/src/serialize/root.zig index 9d54ec5..4d49c1f 100644 --- a/src/serialize/root.zig +++ b/src/serialize/root.zig @@ -12,14 +12,10 @@ fn serializeStruct(allocator: std.mem.Allocator, value: anytype, writer: anytype const ttype = @TypeOf(value); const tinfo = @typeInfo(ttype); if (!std.mem.eql(u8, @tagName(tinfo), "struct")) @panic("non struct type given to serialize"); - const fields = comptime getFields(tinfo); - comptime var i: u8 = 0; - inline while (i < fields.len) { - const field = fields.buffer[i]; + inline for (tinfo.@"struct".fields) |field| { try serializeField(allocator, @typeInfo(field.type), field.name, @field(value, field.name), writer); _ = try writer.write("\n"); - i += 1; } } From 89378b5ab94cc3fe7553e40db84001171d157cb4 Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Sat, 25 Jan 2025 13:15:11 +0530 Subject: [PATCH 08/10] compar enum rather than tag name --- src/serialize/root.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serialize/root.zig b/src/serialize/root.zig index 4d49c1f..3080ced 100644 --- a/src/serialize/root.zig +++ b/src/serialize/root.zig @@ -11,7 +11,7 @@ pub fn serialize(allocator: std.mem.Allocator, obj: anytype, writer: anytype) !v fn serializeStruct(allocator: std.mem.Allocator, value: anytype, writer: anytype) !void { const ttype = @TypeOf(value); const tinfo = @typeInfo(ttype); - if (!std.mem.eql(u8, @tagName(tinfo), "struct")) @panic("non struct type given to serialize"); + if (tinfo != .@"struct") @panic("non struct type given to serialize"); inline for (tinfo.@"struct".fields) |field| { try serializeField(allocator, @typeInfo(field.type), field.name, @field(value, field.name), writer); From 0e605b1be3b0796af68bc5eb3dba58bc52ddac12 Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Sat, 25 Jan 2025 13:19:01 +0530 Subject: [PATCH 09/10] use AnyWriter for writer --- src/serialize/root.zig | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/serialize/root.zig b/src/serialize/root.zig index 3080ced..0baa1d8 100644 --- a/src/serialize/root.zig +++ b/src/serialize/root.zig @@ -1,14 +1,15 @@ const std = @import("std"); const testing = std.testing; const Allocator = std.testing.allocator; +const AnyWriter = std.io.AnyWriter; const MAX_FIELD_COUNT: u8 = 255; -pub fn serialize(allocator: std.mem.Allocator, obj: anytype, writer: anytype) !void { +pub fn serialize(allocator: std.mem.Allocator, obj: anytype, writer: *AnyWriter) !void { try serializeStruct(allocator, obj, writer); } -fn serializeStruct(allocator: std.mem.Allocator, value: anytype, writer: anytype) !void { +fn serializeStruct(allocator: std.mem.Allocator, value: anytype, writer: *AnyWriter) !void { const ttype = @TypeOf(value); const tinfo = @typeInfo(ttype); if (tinfo != .@"struct") @panic("non struct type given to serialize"); @@ -19,7 +20,7 @@ fn serializeStruct(allocator: std.mem.Allocator, value: anytype, writer: anytype } } -fn serializeSimpleValue(allocator: std.mem.Allocator, t: std.builtin.Type, value: anytype, writer: anytype) !void { +fn serializeSimpleValue(allocator: std.mem.Allocator, t: std.builtin.Type, value: anytype, writer: *AnyWriter) !void { switch (t) { .int, .float => try writer.print("{d}", .{value}), .bool => if (value) try writer.print("true", .{}) else try writer.print("false", .{}), @@ -49,7 +50,7 @@ fn serializeSimpleValue(allocator: std.mem.Allocator, t: std.builtin.Type, value } } -fn serializeField(allocator: std.mem.Allocator, t: std.builtin.Type, key: []const u8, value: anytype, writer: anytype) !void { +fn serializeField(allocator: std.mem.Allocator, t: std.builtin.Type, key: []const u8, value: anytype, writer: *AnyWriter) !void { switch (t) { .int, .float, .bool => { try writer.print("{s} = ", .{key}); @@ -123,7 +124,8 @@ test "basic test" { var buf: [1024]u8 = undefined; var stream = std.io.fixedBufferStream(&buf); - var writer = stream.writer(); + var gwriter = stream.writer(); + var writer = gwriter.any(); try serialize(Allocator, t, &writer); std.debug.print("\n{s}", .{buf}); } From 90a0ba43da5012260a6b29a9bf3fa54e25bab676 Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Sat, 25 Jan 2025 13:26:26 +0530 Subject: [PATCH 10/10] fix typo in .slice --- src/serialize/root.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/serialize/root.zig b/src/serialize/root.zig index 0baa1d8..0176c11 100644 --- a/src/serialize/root.zig +++ b/src/serialize/root.zig @@ -25,7 +25,7 @@ fn serializeSimpleValue(allocator: std.mem.Allocator, t: std.builtin.Type, value .int, .float => try writer.print("{d}", .{value}), .bool => if (value) try writer.print("true", .{}) else try writer.print("false", .{}), .pointer => { - if (t.pointer.child == u8 and t.pointer.size == .Slice and t.pointer.is_const) { + if (t.pointer.child == u8 and t.pointer.size == .slice and t.pointer.is_const) { var esc_string = std.ArrayList(u8).init(allocator); defer esc_string.deinit(); const string = value; @@ -58,7 +58,7 @@ fn serializeField(allocator: std.mem.Allocator, t: std.builtin.Type, key: []cons }, .pointer => { try writer.print("{s} = ", .{key}); - if (t.pointer.child == u8 and t.pointer.size == .Slice and t.pointer.is_const) + if (t.pointer.child == u8 and t.pointer.size == .slice and t.pointer.is_const) try serializeSimpleValue(allocator, t, value, writer); }, .array => {