Function valueArbitraryDepth [src]
Serialize a value, similar to serializeArbitraryDepth.
Prototype
pub fn valueArbitraryDepth(self: *Serializer, val: anytype, options: ValueOptions) Error!void
Parameters
self: *Serializer
options: ValueOptions
Possible Errors
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,
}
}