Skip to content

Commit d355863

Browse files
authored
Merge pull request #3 from MasterQ32/init-rework
Tries to rework the init function to normal parameters instead of tuples
2 parents 34386ec + 6fbe2db commit d355863

File tree

2 files changed

+69
-57
lines changed

2 files changed

+69
-57
lines changed

examples.zig

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ test "Simple NonOwning interface" {
2727
};
2828

2929
var f = TestFooer{ .state = 42 };
30-
var fooer = try Fooer.init(.{&f});
30+
var fooer = try Fooer.init(&f);
3131
defer fooer.deinit();
3232

3333
expectEqual(@as(usize, 42), fooer.call("foo", .{}));
@@ -40,6 +40,7 @@ test "Simple NonOwning interface" {
4040
}
4141

4242
test "Comptime only interface" {
43+
// return error.SkipZigTest;
4344
const TestIFace = Interface(struct {
4445
foo: fn (*SelfType, u8) u8,
4546
}, interface.Storage.Comptime);
@@ -54,7 +55,7 @@ test "Comptime only interface" {
5455
}
5556
};
5657

57-
comptime var iface = try TestIFace.init(.{TestType{ .state = 0 }});
58+
comptime var iface = try TestIFace.init(TestType{ .state = 0 });
5859
expectEqual(@as(u8, 42), iface.call("foo", .{42}));
5960
}
6061

@@ -82,7 +83,7 @@ test "Owning interface with optional function" {
8283
}
8384
};
8485

85-
var iface_instance = try TestOwningIface.init(.{ comptime TestStruct{ .state = 0 }, std.testing.allocator });
86+
var iface_instance = try TestOwningIface.init(comptime TestStruct{ .state = 0 }, std.testing.allocator);
8687
defer iface_instance.deinit();
8788

8889
try iface_instance.call("otherFn", .{100});
@@ -117,7 +118,7 @@ test "Interface with virtual async function implemented by an async function" {
117118
};
118119

119120
var i = Impl{ .state = 0 };
120-
var instance = try AsyncIFace.init(.{&i});
121+
var instance = try AsyncIFace.init(&i);
121122
_ = async instance.call("foo", .{});
122123

123124
expectEqual(@as(usize, 0), i.state);
@@ -142,7 +143,7 @@ test "Interface with virtual async function implemented by a blocking function"
142143
}
143144
};
144145

145-
var instance = try AsyncIFace.init(.{Impl{}});
146+
var instance = try AsyncIFace.init(Impl{});
146147

147148
var buf: [256]u8 = undefined;
148149
try await async instance.call("readBytes", .{buf[0..]});

interface.zig

Lines changed: 63 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const assert = std.debug.assert;
66
const expect = std.testing.expect;
77
const expectEqual = std.testing.expectEqual;
88

9-
pub const SelfType = @OpaqueType();
9+
pub const SelfType = @Type(.Opaque);
1010

1111
fn makeSelfPtr(ptr: anytype) *SelfType {
1212
if (comptime !trait.isSingleItemPtr(@TypeOf(ptr))) {
@@ -43,16 +43,21 @@ pub const Storage = struct {
4343
erased_ptr: *SelfType,
4444
ImplType: type,
4545

46-
pub fn init(args: anytype) !Comptime {
47-
if (args.len != 1) {
48-
@compileError("Comptime storage expected a 1-tuple in initialization.");
49-
}
46+
fn makeInit(comptime TInterface: type) type {
47+
return struct {
48+
fn init(obj: anytype) !TInterface {
49+
const ImplType = PtrChildOrSelf(@TypeOf(obj));
5050

51-
var obj = args[0];
51+
comptime var obj_holder = obj;
5252

53-
return Comptime{
54-
.erased_ptr = makeSelfPtr(&obj),
55-
.ImplType = @TypeOf(args[0]),
53+
return TInterface{
54+
.vtable_ptr = &comptime makeVTable(TInterface.VTable, ImplType),
55+
.storage = Comptime{
56+
.erased_ptr = makeSelfPtr(&obj_holder),
57+
.ImplType = @TypeOf(obj),
58+
},
59+
};
60+
}
5661
};
5762
}
5863

@@ -66,13 +71,16 @@ pub const Storage = struct {
6671
pub const NonOwning = struct {
6772
erased_ptr: *SelfType,
6873

69-
pub fn init(args: anytype) !NonOwning {
70-
if (args.len != 1) {
71-
@compileError("NonOwning storage expected a 1-tuple in initialization.");
72-
}
73-
74-
return NonOwning{
75-
.erased_ptr = makeSelfPtr(args[0]),
74+
fn makeInit(comptime TInterface: type) type {
75+
return struct {
76+
fn init(ptr: anytype) !TInterface {
77+
return TInterface{
78+
.vtable_ptr = &comptime makeVTable(TInterface.VTable, PtrChildOrSelf(@TypeOf(ptr))),
79+
.storage = NonOwning{
80+
.erased_ptr = makeSelfPtr(ptr),
81+
},
82+
};
83+
}
7684
};
7785
}
7886

@@ -87,19 +95,22 @@ pub const Storage = struct {
8795
allocator: *mem.Allocator,
8896
mem: []u8,
8997

90-
pub fn init(args: anytype) !Owning {
91-
if (args.len != 2) {
92-
@compileError("Owning storage expected a 2-tuple in initialization.");
93-
}
94-
95-
const AllocT = @TypeOf(args[0]);
98+
fn makeInit(comptime TInterface: type) type {
99+
return struct {
100+
fn init(obj: anytype, allocator: *std.mem.Allocator) !TInterface {
101+
const AllocT = @TypeOf(obj);
96102

97-
var obj = try args[1].create(AllocT);
98-
obj.* = args[0];
103+
var ptr = try allocator.create(AllocT);
104+
ptr.* = obj;
99105

100-
return Owning{
101-
.allocator = args[1],
102-
.mem = std.mem.asBytes(obj)[0..],
106+
return TInterface{
107+
.vtable_ptr = &comptime makeVTable(TInterface.VTable, PtrChildOrSelf(AllocT)),
108+
.storage = Owning{
109+
.allocator = allocator,
110+
.mem = std.mem.asBytes(ptr)[0..],
111+
},
112+
};
113+
}
103114
};
104115
}
105116

@@ -119,23 +130,28 @@ pub const Storage = struct {
119130

120131
mem: [size]u8,
121132

122-
pub fn init(args: anytype) !Self {
123-
if (args.len != 1) {
124-
@compileError("Inline storage expected a 1-tuple in initialization.");
125-
}
126-
127-
const ImplSize = @sizeOf(@TypeOf(args[0]));
128-
129-
if (ImplSize > size) {
130-
@compileError("Type does not fit in inline storage.");
131-
}
132-
133-
var self: Self = undefined;
134-
135-
if (ImplSize > 0) {
136-
std.mem.copy(u8, self.mem[0..], @ptrCast([*]const u8, &args[0])[0..ImplSize]);
137-
}
138-
return self;
133+
fn makeInit(comptime TInterface: type) type {
134+
return struct {
135+
fn init(value: anytype) !TInterface {
136+
const ImplSize = @sizeOf(@TypeOf(value));
137+
138+
if (ImplSize > size) {
139+
@compileError("Type does not fit in inline storage.");
140+
}
141+
142+
var self = Self{
143+
.mem = undefined,
144+
};
145+
if (ImplSize > 0) {
146+
std.mem.copy(u8, self.mem[0..], @ptrCast([*]const u8, &args[0])[0..ImplSize]);
147+
}
148+
149+
return TInterface{
150+
.vtable_ptr = &comptime makeVTable(TInterface.VTable, PtrChildOrSelf(@TypeOf(value))),
151+
.storage = self,
152+
};
153+
}
154+
};
139155
}
140156

141157
pub fn getSelfPtr(self: *Self) *SelfType {
@@ -426,15 +442,10 @@ pub fn Interface(comptime VTableT: type, comptime StorageT: type) type {
426442
storage: StorageT,
427443

428444
const Self = @This();
445+
const VTable = VTableT;
446+
const Storage = StorageT;
429447

430-
pub fn init(args: anytype) !Self {
431-
const ImplType = PtrChildOrSelf(@TypeOf(args.@"0"));
432-
433-
return Self{
434-
.vtable_ptr = &comptime makeVTable(VTableT, ImplType),
435-
.storage = try StorageT.init(args),
436-
};
437-
}
448+
pub const init = StorageT.makeInit(Self).init;
438449

439450
pub fn initWithVTable(vtable_ptr: *const VTableT, args: anytype) !Self {
440451
return .{

0 commit comments

Comments
 (0)