|
| 1 | +const std = @import("std"); |
| 2 | +const Self = @This(); |
| 3 | + |
| 4 | +type: []const u8, |
| 5 | +size: usize = 0, |
| 6 | +ptr: *anyopaque, |
| 7 | + |
| 8 | +pub inline fn init(value: anytype) Self { |
| 9 | + return initExplicit(@TypeOf(value), value); |
| 10 | +} |
| 11 | + |
| 12 | +pub inline fn initExplicit(comptime T: type, value: T) Self { |
| 13 | + var size: usize = @sizeOf(T); |
| 14 | + const ptr: *anyopaque = switch (@typeInfo(T)) { |
| 15 | + .Int, .ComptimeInt => @ptrFromInt(value), |
| 16 | + .Float, .ComptimeFloat => @ptrFromInt(@as(usize, @bitCast(@as(f128, @floatCast(value))))), |
| 17 | + .Enum => @ptrFromInt(@intFromEnum(value)), |
| 18 | + .Struct, .Union => @constCast(&value), |
| 19 | + .Pointer => |p| switch (@typeInfo(p.child)) { |
| 20 | + .Array => blk: { |
| 21 | + size = value.len * @sizeOf(p.child); |
| 22 | + break :blk @ptrCast(@constCast(value.ptr)); |
| 23 | + }, |
| 24 | + else => |f| @compileError("Unsupported pointer type: " ++ @tagName(f)), |
| 25 | + }, |
| 26 | + else => |f| @compileError("Unsupported type: " ++ @tagName(f)), |
| 27 | + }; |
| 28 | + |
| 29 | + return .{ |
| 30 | + .type = @typeName(T), |
| 31 | + .size = size, |
| 32 | + .ptr = ptr, |
| 33 | + }; |
| 34 | +} |
| 35 | + |
| 36 | +pub inline fn cast(self: Self, comptime T: type) error{InvalidCast}!T { |
| 37 | + if (!std.mem.eql(u8, self.type, @typeName(T))) return error.InvalidCast; |
| 38 | + |
| 39 | + return switch (@typeInfo(T)) { |
| 40 | + .Int, .ComptimeInt => @intFromPtr(self.ptr), |
| 41 | + .Float, .ComptimeFloat => @floatCast(@as(f128, @bitCast(self.ptr))), |
| 42 | + .Enum => |e| @enumFromInt(@as(e.tag_type, @ptrFromInt(self.ptr))), |
| 43 | + .Struct, .Union => @ptrCast(@alignCast(self.ptr)), |
| 44 | + .Pointer => |p| switch (@typeInfo(p.child)) { |
| 45 | + .Array => blk: { |
| 46 | + const length = @divExact(self.size, @sizeOf(p.child)); |
| 47 | + break :blk @as([*]p.child, @ptrCast(@alignCast(self.ptr)))[0..length]; |
| 48 | + }, |
| 49 | + else => |f| @compileError("Unsupported pointer type: " ++ @tagName(f)), |
| 50 | + }, |
| 51 | + else => |f| @compileError("Unsupported type: " ++ @tagName(f)), |
| 52 | + }; |
| 53 | +} |
| 54 | + |
| 55 | +pub inline fn len(self: Self, comptime T: type) usize { |
| 56 | + const size = switch (@typeInfo(T)) { |
| 57 | + .Pointer => |p| @sizeOf(p.child), |
| 58 | + else => @sizeOf(T), |
| 59 | + }; |
| 60 | + |
| 61 | + return @divExact(self.size, size); |
| 62 | +} |
0 commit comments