Function valueArbitraryDepth [src]

Serialize a value, similar to serializeArbitraryDepth.

Prototype

pub fn valueArbitraryDepth(self: *Serializer, val: anytype, options: ValueOptions) Error!void

Parameters

self: *Serializeroptions: ValueOptions

Possible Errors

WriteFailed Error

See the Writer implementation for detailed diagnostics.

Source

pub fn valueArbitraryDepth(self: *Serializer, val: anytype, options: ValueOptions) Error!void { comptime assert(canSerializeType(@TypeOf(val))); switch (@typeInfo(@TypeOf(val))) { .int, .comptime_int => if (options.emit_codepoint_literals.emitAsCodepoint(val)) |c| { self.codePoint(c) catch |err| switch (err) { error.InvalidCodepoint => unreachable, // Already validated else => |e| return e, }; } else { try self.int(val); }, .float, .comptime_float => try self.float(val), .bool, .null => try self.writer.print("{}", .{val}), .enum_literal => try self.ident(@tagName(val)), .@"enum" => try self.ident(@tagName(val)), .pointer => |pointer| { // Try to serialize as a string const item: ?type = switch (@typeInfo(pointer.child)) { .array => |array| array.child, else => if (pointer.size == .slice) pointer.child else null, }; if (item == u8 and (pointer.sentinel() == null or pointer.sentinel() == 0) and !options.emit_strings_as_containers) { return try self.string(val); } // Serialize as either a tuple or as the child type switch (pointer.size) { .slice => try self.tupleImpl(val, options), .one => try self.valueArbitraryDepth(val.*, options), else => comptime unreachable, } }, .array => { var container = try self.beginTuple( .{ .whitespace_style = .{ .fields = val.len } }, ); for (val) |item_val| { try container.fieldArbitraryDepth(item_val, options); } try container.end(); }, .@"struct" => |@"struct"| if (@"struct".is_tuple) { var container = try self.beginTuple( .{ .whitespace_style = .{ .fields = @"struct".fields.len } }, ); inline for (val) |field_value| { try container.fieldArbitraryDepth(field_value, options); } try container.end(); } else { // Decide which fields to emit const fields, const skipped: [@"struct".fields.len]bool = if (options.emit_default_optional_fields) b: { break :b .{ @"struct".fields.len, @splat(false) }; } else b: { var fields = @"struct".fields.len; var skipped: [@"struct".fields.len]bool = @splat(false); inline for (@"struct".fields, &skipped) |field_info, *skip| { if (field_info.default_value_ptr) |ptr| { const default: *const field_info.type = @ptrCast(@alignCast(ptr)); const field_value = @field(val, field_info.name); if (std.meta.eql(field_value, default.*)) { skip.* = true; fields -= 1; } } } break :b .{ fields, skipped }; }; // Emit those fields var container = try self.beginStruct( .{ .whitespace_style = .{ .fields = fields } }, ); inline for (@"struct".fields, skipped) |field_info, skip| { if (!skip) { try container.fieldArbitraryDepth( field_info.name, @field(val, field_info.name), options, ); } } try container.end(); }, .@"union" => |@"union"| { comptime assert(@"union".tag_type != null); switch (val) { inline else => |pl, tag| if (@TypeOf(pl) == void) try self.writer.print(".{s}", .{@tagName(tag)}) else { var container = try self.beginStruct(.{ .whitespace_style = .{ .fields = 1 } }); try container.fieldArbitraryDepth( @tagName(tag), pl, options, ); try container.end(); }, } }, .optional => if (val) |inner| { try self.valueArbitraryDepth(inner, options); } else { try self.writer.writeAll("null"); }, .vector => |vector| { var container = try self.beginTuple( .{ .whitespace_style = .{ .fields = vector.len } }, ); for (0..vector.len) |i| { try container.fieldArbitraryDepth(val[i], options); } try container.end(); }, else => comptime unreachable, } }