Skip to content

Instantly share code, notes, and snippets.

@renerocksai
Last active May 18, 2023 14:21
Show Gist options
  • Save renerocksai/cfbef3f6740f3a984f611a0ac3f48ea4 to your computer and use it in GitHub Desktop.
Save renerocksai/cfbef3f6740f3a984f611a0ac3f48ea4 to your computer and use it in GitHub Desktop.
Composing Structs in ZIG
const std = @import("std");
pub const ContextDescriptor = struct {
name: []const u8,
type: type,
};
/// Provide a tuple of structs of type like ContextDescriptor
pub fn MixContexts(comptime context_tuple: anytype) type {
var fields: [context_tuple.len]std.builtin.Type.StructField = undefined;
for (context_tuple, 0..) |t, i| {
var fieldType: type = t.type;
var fieldName: []const u8 = t.name[0..];
var isOptional: bool = false;
if (fieldName[0] == '?') {
fieldType = @Type(.{ .Optional = .{ .child = fieldType } });
fieldName = fieldName[1..];
isOptional = true;
}
fields[i] = .{
.name = fieldName,
.type = fieldType,
.default_value = if (isOptional) &null else null,
.is_comptime = false,
.alignment = 0,
};
}
return @Type(.{
.Struct = .{
.layout = .Auto,
.fields = fields[0..],
.decls = &[_]std.builtin.Type.Declaration{},
.is_tuple = false,
},
});
}
test "context_mixing" {
// just some made-up struct
const User = struct {
name: []const u8,
email: []const u8,
};
// just some made-up struct
const Session = struct {
sessionType: []const u8,
token: []const u8,
valid: bool,
};
const Mixed = MixContexts(
.{
.{ .name = "?user", .type = *User },
.{ .name = "?session", .type = *Session },
},
);
std.debug.print("{any}\n", .{Mixed});
inline for (@typeInfo(Mixed).Struct.fields, 0..) |f, i| {
std.debug.print("field {} : name = {s}, type = {any}\n", .{ i, f.name, f.type });
}
var mixed: Mixed = .{
// it's all optionals which we made default to null in MixContexts
};
std.debug.print("mixed = {any}\n", .{mixed});
// now, the same with non-optionals
const NonOpts = MixContexts(
.{
.{ .name = "user", .type = *User },
.{ .name = "session", .type = *Session },
},
);
var user: User = .{
.name = "renerocksai",
.email = "secret",
};
var session: Session = .{
.sessionType = "bearerToken",
.token = "ABCDEFG",
.valid = false,
};
// this will fail if we don't specify
var nonOpts: NonOpts = .{
.user = &user,
.session = &session,
};
std.debug.print("nonOpts = {any}\n", .{nonOpts});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment