diff options
author | 2022-06-20 21:35:45 -0700 | |
---|---|---|
committer | 2022-06-22 06:56:47 -0700 | |
commit | 624bebd20f76bc637de55e08a6ce309b24ededc5 (patch) | |
tree | 083846eac0beb9b880b141279186065f7bcc8b97 | |
parent | 41b03b5c4c426bd3f2a3c7c6aaf454cee11744f0 (diff) | |
download | bun-624bebd20f76bc637de55e08a6ce309b24ededc5.tar.gz bun-624bebd20f76bc637de55e08a6ce309b24ededc5.tar.zst bun-624bebd20f76bc637de55e08a6ce309b24ededc5.zip |
Add a way to assert memory is not undefined in debug builds
-rw-r--r-- | src/global.zig | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/src/global.zig b/src/global.zig index adf7bed06..d525b5d97 100644 --- a/src/global.zig +++ b/src/global.zig @@ -210,7 +210,7 @@ pub fn copy(comptime Type: type, dest: []Type, src: []const Type) void { const output_end = output.ptr + output.len; if (@ptrToInt(input.ptr) <= @ptrToInt(output.ptr) and @ptrToInt(output_end) <= @ptrToInt(input_end)) { - // input is overlapping with output + // // input is overlapping with output if (input.len > strings.ascii_vector_size) { const input_end_vectorized = input.ptr + input.len - (input.len % strings.ascii_vector_size); while (input.ptr != input_end_vectorized) { @@ -237,4 +237,77 @@ pub fn copy(comptime Type: type, dest: []Type, src: []const Type) void { } } +pub const hasCloneFn = std.meta.trait.multiTrait(.{ std.meta.trait.isContainer, std.meta.trait.hasFn("clone") }); +pub fn cloneWithType(comptime T: type, item: T, allocator: std.mem.Allocator) !T { + if (comptime std.meta.trait.isIndexable(T)) { + const Child = std.meta.Child(T); + assertDefined(item); + + if (comptime hasCloneFn(Child)) { + var slice = try allocator.alloc(Child, std.mem.len(item)); + for (slice) |*val, i| { + val.* = try item[i].clone(allocator); + } + return slice; + } + + if (comptime std.meta.trait.isContainer(Child)) { + @compileError("Expected clone() to exist for slice child: " ++ @typeName(Child)); + } + + return try allocator.dupe(Child, item); + } + + if (comptime hasCloneFn(T)) { + return try item.clone(allocator); + } + + @compileError("Expected clone() to exist for " ++ @typeName(T)); +} + +pub fn clone(val: anytype, allocator: std.mem.Allocator) !@TypeOf(val) { + return cloneWithType(@TypeOf(val), val, allocator); +} +pub const StringBuilder = @import("./string_builder.zig"); + +pub inline fn assertDefined(val: anytype) void { + if (comptime !Environment.allow_assert) return; + const Type = @TypeOf(val); + + if (comptime @typeInfo(Type) == .Optional) { + if (val) |res| { + assertDefined(res); + } + return; + } + + if (comptime std.meta.trait.isSlice(Type)) { + std.debug.assert(val.len < std.math.maxInt(u32) + 1); + std.debug.assert(val.len < std.math.maxInt(u32) + 1); + std.debug.assert(val.len < std.math.maxInt(u32) + 1); + var slice: []Type = undefined; + if (val.len > 0) { + std.debug.assert(@ptrToInt(val.ptr) != @ptrToInt(slice.ptr)); + } + return; + } + + if (comptime @typeInfo(Type) == .Pointer) { + var slice: *Type = undefined; + std.debug.assert(@ptrToInt(val) != @ptrToInt(slice)); + return; + } + + if (comptime @typeInfo(Type) == .Struct) { + inline for (comptime std.meta.fieldNames(Type)) |name| { + assertDefined(@field(val, name)); + } + } +} + pub const LinearFifo = @import("./linear_fifo.zig").LinearFifo; + +/// hash a string +pub fn hash(content: []const u8) u64 { + return std.hash.Wyhash.hash(0, content); +} |