1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
const std = @import("std");
pub const string = []const u8;
pub const stringZ = [:0]const u8;
pub const stringMutable = []u8;
pub const CodePoint = i32;
const bun = @import("./global.zig");
// macOS sets file path limit to 1024
// Since a pointer on x64 is 64 bits and only 46 bits are used
// We can safely store the entire path slice in a single u64.
pub const PathString = packed struct {
const PathIntLen = std.math.IntFittingRange(0, bun.MAX_PATH_BYTES);
pub const use_small_path_string = @bitSizeOf(usize) - @bitSizeOf(PathIntLen) >= 53;
pub const PathInt = if (use_small_path_string) PathIntLen else usize;
pub const PointerIntType = if (use_small_path_string) u53 else usize;
ptr: PointerIntType = 0,
len: PathInt = 0,
const JSC = @import("javascript_core");
pub fn fromJS(value: JSC.JSValue, global: *JSC.JSGlobalObject, exception: JSC.C.ExceptionRef) PathString {
if (!value.jsType().isStringLike()) {
JSC.JSError(JSC.getAllocator(global), "Only path strings are supported for now", .{}, global, exception);
return PathString{};
}
var zig_str = JSC.ZigString.init("");
value.toZigString(&zig_str, global);
return PathString.init(zig_str.slice());
}
pub inline fn asRef(this: PathString) JSC.JSValueRef {
return this.toValue().asObjectRef();
}
pub fn toJS(this: PathString, ctx: JSC.C.JSContextRef, _: JSC.C.ExceptionRef) JSC.C.JSValueRef {
var zig_str = JSC.ZigString.init(this.slice());
zig_str.detectEncoding();
return zig_str.toValueAuto(ctx.ptr()).asObjectRef();
}
pub inline fn slice(this: anytype) string {
@setRuntimeSafety(false); // "cast causes pointer to be null" is fine here. if it is null, the len will be 0.
return @intToPtr([*]u8, @intCast(usize, this.ptr))[0..this.len];
}
pub inline fn sliceAssumeZ(this: anytype) stringZ {
@setRuntimeSafety(false); // "cast causes pointer to be null" is fine here. if it is null, the len will be 0.
return @intToPtr([*:0]u8, @intCast(usize, this.ptr))[0..this.len];
}
pub inline fn init(str: string) @This() {
@setRuntimeSafety(false); // "cast causes pointer to be null" is fine here. if it is null, the len will be 0.
return @This(){
.ptr = @truncate(PointerIntType, @ptrToInt(str.ptr)),
.len = @truncate(PathInt, str.len),
};
}
pub inline fn isEmpty(this: anytype) bool {
return this.len == 0;
}
pub const empty = @This(){ .ptr = 0, .len = 0 };
comptime {
if (!bun.Environment.isWasm) {
if (use_small_path_string and @bitSizeOf(@This()) != 64) {
@compileError("PathString must be 64 bits");
} else if (!use_small_path_string and @bitSizeOf(@This()) != 128) {
@compileError("PathString must be 128 bits");
}
}
}
};
pub const HashedString = struct {
ptr: [*]const u8,
len: u32,
hash: u32,
pub const empty = HashedString{ .ptr = @intToPtr([*]const u8, 0xDEADBEEF), .len = 0, .hash = 0 };
pub fn init(buf: string) HashedString {
return HashedString{
.ptr = buf.ptr,
.len = @truncate(u32, buf.len),
.hash = @truncate(u32, std.hash.Wyhash.hash(0, buf)),
};
}
pub fn initNoHash(buf: string) HashedString {
return HashedString{
.ptr = buf.ptr,
.len = @truncate(u32, buf.len),
.hash = 0,
};
}
pub fn eql(this: HashedString, other: anytype) bool {
return Eql(this, @TypeOf(other), other);
}
pub fn Eql(this: HashedString, comptime Other: type, other: Other) bool {
switch (comptime Other) {
HashedString, *HashedString, *const HashedString => {
return ((@maximum(this.hash, other.hash) > 0 and this.hash == other.hash) or (this.ptr == other.ptr)) and this.len == other.len;
},
else => {
return @as(usize, this.len) == other.len and @truncate(u32, std.hash.Wyhash.hash(0, other[0..other.len])) == this.hash;
},
}
}
pub fn str(this: HashedString) string {
return this.ptr[0..this.len];
}
};
|