Skip to content

Instantly share code, notes, and snippets.

@ikskuh
Created April 23, 2021 08:45
Show Gist options
  • Save ikskuh/bb6e2e69a45ddee1a0a44ff01acdf8bb to your computer and use it in GitHub Desktop.
Save ikskuh/bb6e2e69a45ddee1a0a44ff01acdf8bb to your computer and use it in GitHub Desktop.
std::any implementation in zig
const std = @import("std");
pub fn main() !void {
var allocator = std.heap.page_allocator;
var a = try Any.init(allocator, @as(u32, 10));
defer a.deinit();
var b = try Any.init(allocator, @as([]const u8, "Hello, World!"));
defer b.deinit();
std.debug.print("{s} => {d}\n", .{
b.get([]const u8),
a.get(u32),
});
std.debug.print("a: u32={}\t[]const u8={}\tf32={}\n", .{
a.is(u32), a.is([]const u8), a.is(f32),
});
std.debug.print("b: u32={}\t[]const u8={}\tf32={}\n", .{
b.is(u32), b.is([]const u8), b.is(f32),
});
}
const Any = struct {
allocator: *std.mem.Allocator,
type_key: TypeKey,
buffer: []u8,
fn init(allocator: *std.mem.Allocator, value: anytype) !Any {
const T = @TypeOf(value);
const ptr = try allocator.create(T);
ptr.* = value;
var any = Any {
.allocator = allocator,
.type_key = TypeKeyGenerator().get(@TypeOf(value)),
.buffer = std.mem.asBytes(ptr),
};
std.debug.assert(any.buffer.len == @sizeOf(T));
return any;
}
fn deinit(self: *Any) void {
self.* = undefined;
}
fn is(self: Any, comptime T: type) bool {
return self.type_key == TypeKeyGenerator().get(T);
}
fn get(self: *Any, comptime T: type) T {
std.debug.assert(self.is(T));
return @ptrCast(*T, @alignCast(@alignOf(T), self.buffer.ptr)).*;
}
};
const TypeKey = enum(u32) { _ };
fn TypeKeyGenerator() type {
comptime var counter: u32 = 0; // this gets comptime closed
return struct {
pub fn get(comptime T: type) TypeKey {
defer counter += 1;
return @intToEnum(TypeKey, counter);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment