41 lines
1.7 KiB
Zig
41 lines
1.7 KiB
Zig
const std = @import("std");
|
|
|
|
pub fn Partial(comptime T: type) type {
|
|
const info = @typeInfo(T);
|
|
switch (info) {
|
|
.@"struct" => |s| {
|
|
comptime var fields: []const std.builtin.Type.StructField = &[_]std.builtin.Type.StructField{};
|
|
inline for (s.fields) |field| {
|
|
if (field.is_comptime) {
|
|
@compileError("Cannot make Partial of " ++ @typeName(T) ++ ", it has a comptime field " ++ field.name);
|
|
}
|
|
const optional_type = switch (@typeInfo(field.type)) {
|
|
.optional => field.type,
|
|
else => ?field.type,
|
|
};
|
|
const default_value: optional_type = null;
|
|
const aligned_ptr: *align(field.alignment) const anyopaque = @alignCast(@ptrCast(&default_value));
|
|
const optional_field: [1]std.builtin.Type.StructField = [_]std.builtin.Type.StructField{.{
|
|
.alignment = field.alignment,
|
|
.default_value = aligned_ptr,
|
|
.is_comptime = false,
|
|
.name = field.name,
|
|
.type = optional_type,
|
|
}};
|
|
fields = fields ++ optional_field;
|
|
}
|
|
const partial_type_info: std.builtin.Type = .{ .@"struct" = .{
|
|
.backing_integer = s.backing_integer,
|
|
.decls = &[_]std.builtin.Type.Declaration{},
|
|
.fields = fields,
|
|
.is_tuple = s.is_tuple,
|
|
.layout = s.layout,
|
|
} };
|
|
return @Type(partial_type_info);
|
|
},
|
|
else => @compileError("Cannot make Partial of " ++ @typeName(T) ++
|
|
", the type must be a struct"),
|
|
}
|
|
unreachable;
|
|
}
|