Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

valueArbitraryDepth

Serialize a value, similar to serializeArbitraryDepth.

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

File

lib/std/zon/Serializer.zig:124

Code

pub fn valueArbitraryDepth(self: *Serializer, val: anytype, options: ValueOptions) Error!void {
    comptime assertCanSerializeType(@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 => {
            try valueArbitraryDepthArray(self, @TypeOf(val), &val, options);
        },
        .vector => |vector| {
            const array: [vector.len]vector.child = val;
            try valueArbitraryDepthArray(self, @TypeOf(array), &array, options);
        },
        .@"struct" => |@"struct"| if (@"struct".is_tuple) {
            var container = try self.beginTuple(
                .{ .whitespace_style = .{ .fields = @"struct".field_names.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".field_names.len]bool = if (options.emit_default_optional_fields) b: {
                break :b .{ @"struct".field_names.len, @splat(false) };
            } else b: {
                var fields = @"struct".field_names.len;
                var skipped: [@"struct".field_names.len]bool = @splat(false);
                inline for (
                    @"struct".field_names,
                    @"struct".field_types,
                    @"struct".field_attrs,
                    &skipped,
                ) |field_name, field_type, field_attrs, *skip| {
                    if (field_attrs.default_value_ptr) |ptr| {
                        const default: *const field_type = @ptrCast(@alignCast(ptr));
                        const field_value = @field(val, field_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".field_names, skipped) |field_name, skip| {
                if (!skip) {
                    try container.fieldArbitraryDepth(
                        field_name,
                        @field(val, field_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");
        },

        else => comptime unreachable,
    }
}