Last active
May 18, 2023 14:21
-
-
Save renerocksai/cfbef3f6740f3a984f611a0ac3f48ea4 to your computer and use it in GitHub Desktop.
Composing Structs in ZIG
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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