Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 54 additions & 47 deletions src/block.zig
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ pub fn Block(
};
ctx.invoke = @ptrCast(func);
ctx.descriptor = &descriptor;
inline for (captures_info.fields) |field| {
@field(ctx, field.name) = @field(captures, field.name);
inline for (captures_info.field_names) |field_name| {
@field(ctx, field_name) = @field(captures, field_name);
}

return ctx;
Expand Down Expand Up @@ -123,11 +123,11 @@ pub fn Block(
fn descCopyHelper(dst: *anyopaque, src: *anyopaque) callconv(.c) void {
const real_dst: *Context = @ptrCast(@alignCast(dst));
const real_src: *Context = @ptrCast(@alignCast(src));
inline for (captures_info.fields) |field| {
if (field.type == objc.c.id) {
inline for (captures_info.field_names, captures_info.field_types) |field_name, field_type| {
if (field_type == objc.c.id) {
_Block_object_assign(
@ptrCast(&@field(real_dst, field.name)),
@field(real_src, field.name),
@ptrCast(&@field(real_dst, field_name)),
@field(real_src, field_name),
.object,
);
}
Expand All @@ -136,10 +136,10 @@ pub fn Block(

fn descDisposeHelper(src: *anyopaque) callconv(.c) void {
const real_src: *Context = @ptrCast(@alignCast(src));
inline for (captures_info.fields) |field| {
if (field.type == objc.c.id) {
inline for (captures_info.field_names, captures_info.field_types) |field_name, field_type| {
if (field_type == objc.c.id) {
_Block_object_dispose(
@field(real_src, field.name),
@field(real_src, field_name),
.object,
);
}
Expand All @@ -163,59 +163,66 @@ pub fn Block(
/// argument to any block invocation. See Block.
fn BlockContext(comptime Captures: type, comptime InvokeFn: type) type {
const captures_info = @typeInfo(Captures).@"struct";
var fields: [captures_info.fields.len + 5]std.builtin.Type.StructField = undefined;
fields[0] = .{
.name = "isa",
.type = ?*anyopaque,
const field_count = captures_info.field_types.len + 5;

var field_names: [field_count][]const u8 = undefined;
var field_types: [field_count]type = undefined;
var field_attrs: [field_count]std.lang.Type.Struct.FieldAttributes = undefined;

field_names[0] = "isa";
field_types[0] = ?*anyopaque;
field_attrs[0] = .{
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(*anyopaque),
.@"comptime" = false,
.@"align" = @alignOf(*anyopaque),
};
fields[1] = .{
.name = "flags",
.type = BlockFlags,
field_names[1] = "flags";
field_types[1] = BlockFlags;
field_attrs[1] = .{
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(c_int),
.@"comptime" = false,
.@"align" = @alignOf(c_int),
};
fields[2] = .{
.name = "reserved",
.type = c_int,
field_names[2] = "reserved";
field_types[2] = c_int;
field_attrs[2] = .{
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(c_int),
.@"comptime" = false,
.@"align" = @alignOf(c_int),
};
fields[3] = .{
.name = "invoke",
.type = *const InvokeFn,
field_names[3] = "invoke";
field_types[3] = *const InvokeFn;
field_attrs[3] = .{
.default_value_ptr = null,
.is_comptime = false,
.alignment = @typeInfo(*const InvokeFn).pointer.alignment,
.@"comptime" = false,
.@"align" = @typeInfo(*const InvokeFn).pointer.attrs.@"align",
};
fields[4] = .{
.name = "descriptor",
.type = *const Descriptor,
field_names[4] = "descriptor";
field_types[4] = *const Descriptor;
field_attrs[4] = .{
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(*Descriptor),
.@"comptime" = false,
.@"align" = @alignOf(*Descriptor),
};

for (captures_info.fields, 5..) |capture, i| {
switch (capture.type) {
for (
captures_info.field_names,
captures_info.field_types,
captures_info.field_attrs,
5..,
) |field_name, field_type, field_attr, i| {
switch (field_type) {
comptime_int => @compileError("capture should not be a comptime_int, try using @as"),
comptime_float => @compileError("capture should not be a comptime_float, try using @as"),
else => {},
}
fields[i] = .{ .name = capture.name, .type = capture.type, .default_value_ptr = null, .is_comptime = false, .alignment = capture.alignment };
}

var field_names: [fields.len][]const u8 = undefined;
var field_types: [fields.len]type = undefined;
var field_attrs: [fields.len]std.builtin.Type.StructField.Attributes = undefined;
for (fields, 0..) |field, i| {
field_names[i] = field.name;
field_types[i] = field.type;
field_attrs[i] = .{ .@"align" = field.alignment };
field_names[i] = field_name;
field_types[i] = field_type;
field_attrs[i] = .{
.default_value_ptr = null,
.@"comptime" = false,
.@"align" = field_attr.@"align",
};
}

return @Struct(.@"extern", null, &field_names, &field_types, &field_attrs);
Expand Down
20 changes: 10 additions & 10 deletions src/class.zig
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ pub const Class = struct {
// whose first two arguments are a `c.id` and a `c.SEL`.
pub fn replaceMethod(self: Class, name: [:0]const u8, imp: anytype) void {
const fn_info = @typeInfo(@TypeOf(imp)).@"fn";
assert(std.meta.eql(fn_info.calling_convention, std.builtin.CallingConvention.c));
assert(fn_info.is_var_args == false);
assert(fn_info.params.len >= 2);
assert(fn_info.params[0].type == c.id);
assert(fn_info.params[1].type == c.SEL);
assert(std.meta.eql(fn_info.attrs.@"callconv", std.lang.CallingConvention.c));
assert(fn_info.attrs.varargs == false);
assert(fn_info.param_types.len >= 2);
assert(fn_info.param_types[0] == c.id);
assert(fn_info.param_types[1] == c.SEL);
_ = c.class_replaceMethod(self.value, objc.sel(name).value, @ptrCast(&imp), null);
}

Expand All @@ -72,11 +72,11 @@ pub const Class = struct {
pub fn addMethod(self: Class, name: [:0]const u8, imp: anytype) bool {
const Fn = @TypeOf(imp);
const fn_info = @typeInfo(Fn).@"fn";
assert(std.meta.eql(fn_info.calling_convention, std.builtin.CallingConvention.c));
assert(fn_info.is_var_args == false);
assert(fn_info.params.len >= 2);
assert(fn_info.params[0].type == c.id);
assert(fn_info.params[1].type == c.SEL);
assert(std.meta.eql(fn_info.attrs.@"callconv", std.lang.CallingConvention.c));
assert(fn_info.attrs.varargs == false);
assert(fn_info.param_types.len >= 2);
assert(fn_info.param_types[0] == c.id);
assert(fn_info.param_types[1] == c.SEL);
const encoding = comptime objc.comptimeEncode(Fn);
return boolResult(c.class_addMethod(
self.value,
Expand Down
14 changes: 7 additions & 7 deletions src/encoding.zig
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ pub const Encoding = union(enum) {
// of the struct (determined by levels of pointer indirection)
if (s.show_type_spec) {
try writer.writeAll("=");
inline for (struct_info.@"struct".fields) |field| {
const field_encode = init(field.type);
inline for (struct_info.@"struct".field_types) |field_type| {
const field_encode = init(field_type);
try field_encode.format(writer);
}
}
Expand All @@ -167,8 +167,8 @@ pub const Encoding = union(enum) {
// of the Union (determined by levels of pointer indirection)
if (u.show_type_spec) {
try writer.writeAll("=");
inline for (union_info.@"union".fields) |field| {
const field_encode = init(field.type);
inline for (union_info.@"union".field_types) |field_type| {
const field_encode = init(field_type);
try field_encode.format(writer);
}
}
Expand Down Expand Up @@ -210,13 +210,13 @@ pub const Encoding = union(enum) {
}
},
.function => |fn_info| {
assert(std.meta.eql(fn_info.calling_convention, std.builtin.CallingConvention.c));
assert(std.meta.eql(fn_info.attrs.@"callconv", std.builtin.CallingConvention.c));

// Return type is first in a method encoding
const ret_type_enc = init(fn_info.return_type.?);
try ret_type_enc.format(writer);
inline for (fn_info.params) |param| {
const param_enc = init(param.type.?);
inline for (fn_info.param_types) |param_type| {
const param_enc = init(param_type.?);
try param_enc.format(writer);
}
},
Expand Down
4 changes: 2 additions & 2 deletions src/iterator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const NSFastEnumerationState = extern struct {
state: c_ulong = 0,
itemsPtr: ?[*]objc.c.id = null,
mutationsPtr: ?*c_ulong = null,
extra: [5]c_ulong = [_]c_ulong{0} ** 5,
extra: [5]c_ulong = @splat(0),
};

/// An iterator that uses the fast enumeration protocol[1] to iterate over
Expand All @@ -20,7 +20,7 @@ pub const Iterator = struct {
state: NSFastEnumerationState = .{},
initial_mutations_value: ?c_ulong = null,
// Clang compiles `for…in` loops with a size 16 buffer.
buffer: [16]objc.c.id = [_]objc.c.id{null} ** 16,
buffer: [16]objc.c.id = @splat(null),
slice: []const objc.c.id = &.{},

pub fn init(object: objc.Object) Iterator {
Expand Down
20 changes: 10 additions & 10 deletions src/msg_send.zig
Original file line number Diff line number Diff line change
Expand Up @@ -195,18 +195,18 @@ fn MsgSendFn(
assert(@sizeOf(Target) == @sizeOf(c.id));

// Build up our argument types for @Fn
var param_types: [argsInfo.fields.len + 2]type = undefined;
var param_types: [argsInfo.field_types.len + 2]type = undefined;
param_types[0] = Target;
param_types[1] = c.SEL;
for (argsInfo.fields, 0..) |field, i| param_types[i + 2] = unwrapType(field.type);
for (argsInfo.field_types, 0..) |field_type, i| param_types[i + 2] = unwrapType(field_type);

return @Fn(&param_types, &@splat(.{}), Return, .{ .@"callconv" = .c });
}

fn UnwrappedArgs(comptime Args: type) type {
const fields = @typeInfo(Args).@"struct".fields;
var types: [fields.len]type = undefined;
for (fields, 0..) |field, i| types[i] = unwrapType(field.type);
const field_types = @typeInfo(Args).@"struct".field_types;
var types: [field_types.len]type = undefined;
for (field_types, 0..) |field_type, i| types[i] = unwrapType(field_type);
return @Tuple(&types);
}

Expand All @@ -221,9 +221,9 @@ fn unwrapType(comptime T: type) type {
// rather than c.id, since Class and Sel have distinct pointer types.
if (@typeInfo(T) == .@"struct") {
const info = @typeInfo(T).@"struct";
for (info.fields) |field| {
if (std.mem.eql(u8, field.name, "value") and @sizeOf(field.type) == @sizeOf(c.id)) {
return field.type;
for (info.field_names, info.field_types) |field_name, field_type| {
if (std.mem.eql(u8, field_name, "value") and @sizeOf(field_type) == @sizeOf(c.id)) {
return field_type;
}
}
}
Expand Down Expand Up @@ -255,9 +255,9 @@ fn unwrapType(comptime T: type) type {
}

inline fn buildUnwrappedArgs(args: anytype) UnwrappedArgs(@TypeOf(args)) {
const fields = @typeInfo(@TypeOf(args)).@"struct".fields;
const field_types = @typeInfo(@TypeOf(args)).@"struct".field_types;
var result: UnwrappedArgs(@TypeOf(args)) = undefined;
inline for (fields, 0..) |_, i| {
inline for (field_types, 0..) |_, i| {
result[i] = if (unwrapType(@TypeOf(args[i])) != @TypeOf(args[i]))
args[i].value
else
Expand Down