Skip to content

Instantly share code, notes, and snippets.

@Gonzih
Last active January 13, 2023 00:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gonzih/2b0d6e1a33f61fcc78f25c22630a5bd9 to your computer and use it in GitHub Desktop.
Save Gonzih/2b0d6e1a33f61fcc78f25c22630a5bd9 to your computer and use it in GitHub Desktop.
Zig fat pointer example
const std = @import("std");
const testing = std.testing;
const assert = std.debug.assert;
pub const Runner = struct {
const Self = @This();
const VTable = struct { add: *const fn (*anyopaque, *usize) void };
vtable: *const VTable,
ptr: *anyopaque,
fn make(pointer: anytype) Self {
const Ptr = @TypeOf(pointer);
const ptr_info = @typeInfo(Ptr);
const alignment = ptr_info.Pointer.alignment;
assert(ptr_info == .Pointer);
assert(ptr_info.Pointer.size == .One);
assert(@typeInfo(ptr_info.Pointer.child) == .Struct);
const gen = struct {
fn addImpl(ptr: *anyopaque, ctx: *usize) void {
const self = @ptrCast(Ptr, @alignCast(alignment, ptr));
try @call(.{ .modifier = .always_inline }, std.meta.Child(Ptr).add, .{ self, ctx });
}
const vtable = VTable{
.add = addImpl,
};
};
return .{
.ptr = pointer,
.vtable = &gen.vtable,
};
}
fn add(self: *@This(), ctx: *usize) void {
self.vtable.add(self.ptr, ctx);
}
};
test "basic add functionality" {
const Runner1 = struct {
const Self = @This();
c: usize = 10,
pub fn add(self: *Self, acc: *usize) !void {
acc.* += self.c;
}
};
var acc: usize = 0;
var r = Runner1{};
var r1 = Runner.make(&r);
r1.add(&acc);
try testing.expect(acc == 10);
r1.add(&acc);
try testing.expect(acc == 20);
}
// https://zig.news/kilianvounckx/zig-interfaces-for-the-uninitiated-an-update-4gf1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment