DoxigAlpha

valueArbitraryDepth

Serialize a value, similar to serializeArbitraryDepth.

Function parameters

Parameters

#
self:*Serializer
val:anytype

Type definitions in this namespace

Types

#
ContainerOptions
Options for manual serialization of container types.
ValueOptions
Options for serialization of an individual value.
EmitCodepointLiterals
Determines when to emit Unicode code point literals as opposed to integer literals.
MultilineStringOptions
Options for formatting multiline strings.
Tuple
Writes ZON tuples field by field.
Struct
Writes ZON structs field by field.

Serialize a value, similar to `serialize`.

Functions

#
value
Serialize a value, similar to `serialize`.
valueMaxDepth
Serialize a value, similar to `serializeMaxDepth`.
valueArbitraryDepth
Serialize a value, similar to `serializeArbitraryDepth`.
int
Serialize an integer.
float
Serialize a float.
ident
Serialize `name` as an identifier prefixed with `.`.
codePoint
Serialize `val` as a Unicode codepoint.
tuple
Like `value`, but always serializes `val` as a tuple.
tupleMaxDepth
Like `tuple`, but recursive types are allowed.
tupleArbitraryDepth
Like `tuple`, but recursive types are allowed.
string
Like `value`, but always serializes `val` as a string.
multilineString
Like `value`, but always serializes to a multiline string literal.
beginStruct
Create a `Struct` for writing ZON structs field by field.
beginTuple
Creates a `Tuple` for writing ZON tuples field by field.

Error sets in this namespace

Error Sets

#

Source

Implementation

#
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,
    }
}