@@ -106,7 +106,7 @@ pub const StructSerializer = struct {
106106 // Sub-tables and array-of-tables are deferred to appear after scalar fields.
107107 // Unions with payload variants also serialize as sub-tables (external tag
108108 // produces a struct with one key = variant name).
109- if (k == .@"struct" ) {
109+ if (k == .@"struct" or k == .map ) {
110110 try self .deferSubTable (key , value , false );
111111 return ;
112112 }
@@ -133,9 +133,74 @@ pub const StructSerializer = struct {
133133 }
134134
135135 pub fn serializeEntry (self : * StructSerializer , key : anytype , value : anytype ) Error ! void {
136- _ = key ;
137- _ = value ;
138- _ = self ;
136+ const V = @TypeOf (value );
137+ const k = comptime kind_mod .typeKind (V );
138+
139+ if (k == .optional ) {
140+ if (value == null ) return ;
141+ return self .serializeEntry (key , value .? );
142+ }
143+
144+ if (k == .@"struct" or k == .map or (k == .@"union" and comptime unionHasPayload (V ))) {
145+ try self .deferSubTableDynamic (key , value );
146+ return ;
147+ }
148+
149+ const K = @TypeOf (key );
150+ if (K == []const u8 ) {
151+ writeTomlKey (self .out , key ) catch return error .WriteFailed ;
152+ } else if (comptime @typeInfo (K ) == .int ) {
153+ self .out .print ("{d}" , .{key }) catch return error .WriteFailed ;
154+ } else {
155+ @compileError ("unsupported map key type for TOML: " ++ @typeName (K ));
156+ }
157+ self .out .writeAll (" = " ) catch return error .WriteFailed ;
158+
159+ var child = Serializer {
160+ .out = self .out ,
161+ .allocator = self .allocator ,
162+ .path = self .path ,
163+ };
164+ try core_serialize .serialize (V , value , & child , .{});
165+ self .out .writeByte ('\n ' ) catch return error .WriteFailed ;
166+ }
167+
168+ fn deferSubTableDynamic (self : * StructSerializer , key : []const u8 , value : anytype ) Error ! void {
169+ var aw : std.io.Writer.Allocating = .init (self .allocator );
170+
171+ const new_path = self .allocator .alloc ([]const u8 , self .path .len + 1 ) catch return error .OutOfMemory ;
172+ @memcpy (new_path [0.. self .path .len ], self .path );
173+ new_path [self .path .len ] = key ;
174+
175+ aw .writer .writeByte ('\n ' ) catch return error .WriteFailed ;
176+ aw .writer .writeByte ('[' ) catch return error .WriteFailed ;
177+ for (new_path , 0.. ) | seg , i | {
178+ if (i > 0 ) aw .writer .writeByte ('.' ) catch return error .WriteFailed ;
179+ writeTomlKey (& aw .writer , seg ) catch return error .WriteFailed ;
180+ }
181+ aw .writer .writeAll ("]\n " ) catch return error .WriteFailed ;
182+
183+ var child_ser = Serializer {
184+ .out = & aw .writer ,
185+ .allocator = self .allocator ,
186+ .path = new_path ,
187+ };
188+ core_serialize .serialize (@TypeOf (value ), value , & child_ser , .{}) catch {
189+ self .allocator .free (new_path );
190+ aw .deinit ();
191+ return error .WriteFailed ;
192+ };
193+ self .allocator .free (new_path );
194+
195+ const data = aw .toOwnedSlice () catch return error .OutOfMemory ;
196+ self .deferred .append (self .allocator , .{
197+ .key = key ,
198+ .data = data ,
199+ .is_array_of_tables = false ,
200+ }) catch {
201+ self .allocator .free (data );
202+ return error .OutOfMemory ;
203+ };
139204 }
140205
141206 pub fn end (self : * StructSerializer ) Error ! void {
0 commit comments