Skip to content

Commit f9244f5

Browse files
feat(anytype): comments and tests
1 parent a931766 commit f9244f5

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

any+/anytype.zig

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ type: []const u8,
55
size: usize = 0,
66
ptr: *anyopaque,
77

8+
/// Initializes a runtime anytype from a comptime anytype.
89
pub inline fn init(value: anytype) Self {
910
return initExplicit(@TypeOf(value), value);
1011
}
1112

13+
/// Explicitly initialize a runtime anytype to fit the type T.
1214
pub inline fn initExplicit(comptime T: type, value: T) Self {
1315
var size: usize = @sizeOf(T);
1416
const ptr: *anyopaque = switch (@typeInfo(T)) {
@@ -33,25 +35,32 @@ pub inline fn initExplicit(comptime T: type, value: T) Self {
3335
};
3436
}
3537

38+
/// Safely casts from the anytype to the real type.
39+
/// This returns an error if the cast cannot be made safely.
3640
pub inline fn cast(self: Self, comptime T: type) error{InvalidCast}!T {
3741
if (!std.mem.eql(u8, self.type, @typeName(T))) return error.InvalidCast;
42+
return self.unsafeCast(T);
43+
}
3844

45+
/// Casts a type without any of the safety
46+
pub inline fn unsafeCast(self: Self, comptime T: type) T {
3947
return switch (@typeInfo(T)) {
4048
.Int, .ComptimeInt => @intFromPtr(self.ptr),
4149
.Float, .ComptimeFloat => @floatCast(@as(f128, @bitCast(self.ptr))),
4250
.Enum => |e| @enumFromInt(@as(e.tag_type, @ptrFromInt(self.ptr))),
4351
.Struct, .Union => @ptrCast(@alignCast(self.ptr)),
4452
.Pointer => |p| switch (@typeInfo(p.child)) {
4553
.Array => blk: {
46-
const length = @divExact(self.size, @sizeOf(p.child));
47-
break :blk @as([*]p.child, @ptrCast(@alignCast(self.ptr)))[0..length];
54+
break :blk @as([*]p.child, @ptrCast(@alignCast(self.ptr)))[0..self.len(T)];
4855
},
4956
else => |f| @compileError("Unsupported pointer type: " ++ @tagName(f)),
5057
},
5158
else => |f| @compileError("Unsupported type: " ++ @tagName(f)),
5259
};
5360
}
5461

62+
/// Returns the number of elements in the anytype.
63+
/// If 1 is returned, it could be a single element type.
5564
pub inline fn len(self: Self, comptime T: type) usize {
5665
const size = switch (@typeInfo(T)) {
5766
.Pointer => |p| @sizeOf(p.child),
@@ -60,3 +69,17 @@ pub inline fn len(self: Self, comptime T: type) usize {
6069

6170
return @divExact(self.size, size);
6271
}
72+
73+
test "Casting integers and floats" {
74+
comptime var i: usize = 0;
75+
inline while (i < std.math.maxInt(u8)) : (i += 1) {
76+
try std.testing.expectEqual(i, try initExplicit(u8, i).cast(u8));
77+
}
78+
79+
try std.testing.expectEqual(123.456, try initExplicit(f32, 123.456).cast(f32));
80+
}
81+
82+
test "Invalid casts" {
83+
try std.testing.expectError(error.InvalidCast, initExplicit(f32, 123.456).cast(u8));
84+
try std.testing.expectError(error.InvalidCast, initExplicit(f32, 123.456).cast(f128));
85+
}

0 commit comments

Comments
 (0)