it compiled

This commit is contained in:
Jarred Sumner
2024-11-25 05:49:35 -08:00
parent 62e451caea
commit 99ed017f48
3 changed files with 149 additions and 85 deletions

View File

@@ -741,7 +741,7 @@ pub const MySQLConnection = struct {
this.ref();
const vm = this.globalObject.bunVM();
defer {
if (this.status == .connected and this.requests.items.len == 0 and this.write_buffer.remaining().len == 0) {
if (this.status == .connected and this.requests.readableLength() == 0 and this.write_buffer.remaining().len == 0) {
// Don't keep the process alive when there's nothing to do.
this.poll_ref.unref(vm);
} else if (this.status == .connected) {
@@ -823,12 +823,12 @@ pub const MySQLConnection = struct {
// Read packet header
const header = protocol.PacketHeader.decode(reader.peek()) orelse break;
try reader.skip(protocol.PACKET_HEADER_SIZE);
reader.skip(protocol.PACKET_HEADER_SIZE);
// Ensure we have the full packet
reader.ensureCapacity(header.length) catch |err| {
if (err == error.ShortRead) {
try reader.skip(-@as(isize, @intCast(protocol.PACKET_HEADER_SIZE)));
reader.skip(-@as(isize, @intCast(protocol.PACKET_HEADER_SIZE)));
}
return err;
@@ -848,7 +848,7 @@ pub const MySQLConnection = struct {
},
}
try reader.skip(header.length);
reader.skip(header.length);
}
}
@@ -908,7 +908,7 @@ pub const MySQLConnection = struct {
pub fn handleAuth(this: *MySQLConnection, comptime Context: type, reader: protocol.NewReader(Context)) !void {
const first_byte = try reader.int(u8);
try reader.skip(-1);
reader.skip(-1);
switch (first_byte) {
@intFromEnum(protocol.PacketType.OK) => {
@@ -1017,7 +1017,7 @@ pub const MySQLConnection = struct {
};
}
try response.writeInternal(Writer, this.writer());
try response.write(this.writer());
this.flushData();
}
@@ -1031,7 +1031,7 @@ pub const MySQLConnection = struct {
.temporary = try auth_method.scramble(this.password, plugin_data, &scrambled_buf),
};
try response.writeInternal(Writer, this.writer());
try response.write(this.writer());
this.flushData();
}
@@ -1090,7 +1090,7 @@ pub const MySQLConnection = struct {
return;
}
this.connection.read_buffer.head += ucount;
this.connection.read_buffer.head += @intCast(ucount);
}
pub fn ensureCapacity(this: Reader, count: usize) bool {
@@ -1132,7 +1132,7 @@ pub const MySQLConnection = struct {
pub fn handlePreparedStatement(this: *MySQLConnection, comptime Context: type, reader: protocol.NewReader(Context)) !void {
const first_byte = try reader.int(u8);
try reader.skip(-1);
reader.skip(-1);
switch (first_byte) {
@intFromEnum(protocol.PacketType.OK) => {
@@ -1212,7 +1212,7 @@ pub const MySQLConnection = struct {
pub fn handleResultSet(this: *MySQLConnection, comptime Context: type, reader: protocol.NewReader(Context)) !void {
const first_byte = try reader.int(u8);
try reader.skip(-1);
reader.skip(-1);
switch (first_byte) {
@intFromEnum(protocol.PacketType.OK) => {
@@ -1265,7 +1265,7 @@ pub const MySQLConnection = struct {
// Start reading rows
while (true) {
const row_first_byte = try reader.byte();
try reader.skip(-1);
reader.skip(-1);
switch (row_first_byte) {
@intFromEnum(protocol.PacketType.EOF) => {
@@ -1300,12 +1300,12 @@ pub const MySQLConnection = struct {
.binary = request.binary,
};
defer row.deinit(allocator);
try row.decodeInternal(allocator, Context, reader);
try row.decode(allocator, reader);
const pending_value = MySQLQuery.pendingValueGetCached(request.thisValue) orelse .zero;
// Process row data
const row_value = row.toJS(request.statement.?.structure(request.thisValue, globalThis), pending_value, request.globalThis);
const row_value = row.toJS(request.statement.?.structure(request.thisValue, globalThis), pending_value, globalThis);
if (globalThis.hasException()) {
request.onJSError(globalThis.tryTakeException().?, globalThis);
return error.JSError;
@@ -1329,7 +1329,7 @@ pub const MySQLConnection = struct {
.statement_id = statement.statement_id,
};
try close.writeInternal(Writer, this.writer());
try close.write(this.writer());
this.flushData();
}
@@ -1338,7 +1338,7 @@ pub const MySQLConnection = struct {
.statement_id = statement.statement_id,
};
try reset.writeInternal(Writer, this.writer());
try reset.write(this.writer());
this.flushData();
}
};
@@ -1346,7 +1346,7 @@ pub const MySQLConnection = struct {
pub const MySQLStatement = struct {
cached_structure: JSC.Strong = .{},
ref_count: u32 = 1,
statement_id: u32,
statement_id: u32 = 0,
params: []const types.FieldType = &[_]types.FieldType{},
columns: []const protocol.ColumnDefinition41 = &[_]protocol.ColumnDefinition41{},
signature: Signature,
@@ -1508,7 +1508,7 @@ pub const MySQLQuery = struct {
};
defer execute.deinit();
try this.bind(&execute, globalObject);
try execute.writeInternal(writer);
try execute.write(writer);
this.status = .written;
}
@@ -1535,7 +1535,7 @@ pub const MySQLQuery = struct {
// TODO: unsigned
false,
);
defer value.deinit();
defer value.deinit(bun.default_allocator);
params[i] = try value.toData(param);
i += 1;
}
@@ -1674,6 +1674,14 @@ pub const MySQLQuery = struct {
return .undefined;
}
pub fn doCancel(this: *MySQLQuery, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSValue {
_ = callframe;
_ = globalObject;
_ = this;
return .undefined;
}
pub fn doRun(this: *MySQLQuery, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSValue {
var arguments_ = callframe.arguments_old(2);
const arguments = arguments_.slice();
@@ -1739,6 +1747,7 @@ pub const MySQLQuery = struct {
.signature = signature,
.ref_count = 2,
.status = .parsing,
.statement_id = 0,
};
this.statement = stmt;
entry.value_ptr.* = stmt;

View File

@@ -45,7 +45,7 @@ pub const StackReader = struct {
this.message_start.* = this.offset.*;
}
pub fn ensureLength(this: @This(), length: usize) bool {
pub fn ensureCapacity(this: @This(), length: usize) bool {
return this.buffer.len >= (this.offset.* + length);
}
@@ -83,10 +83,6 @@ pub const StackReader = struct {
this.offset.* += ucount;
}
pub fn ensureCapacity(this: StackReader, count: usize) bool {
return this.buffer.len >= (this.offset.* + count);
}
pub fn read(this: StackReader, count: usize) anyerror!Data {
const offset = this.offset.*;
if (!this.ensureCapacity(count)) {
@@ -126,17 +122,19 @@ pub fn NewWriterWrap(
const offsetFn = offsetFn_;
pub const Ctx = Context;
pub const is_wrapped = true;
pub const WrappedWriter = @This();
pub inline fn write(this: @This(), data: []const u8) anyerror!void {
pub fn write(this: @This(), data: []const u8) anyerror!void {
try writeFn(this.wrapped, data);
}
pub inline fn offset(this: @This()) usize {
pub fn offset(this: @This()) usize {
return offsetFn(this.wrapped);
}
pub inline fn pwrite(this: @This(), data: []const u8, i: usize) anyerror!void {
pub fn pwrite(this: @This(), data: []const u8, i: usize) anyerror!void {
try pwriteFn(this.wrapped, data, i);
}
@@ -195,24 +193,26 @@ pub fn NewReaderWrap(
pub const Ctx = Context;
pub inline fn markMessageStart(this: @This()) void {
pub const is_wrapped = true;
pub fn markMessageStart(this: @This()) void {
markMessageStartFn(this.wrapped);
}
pub inline fn read(this: @This(), count: usize) anyerror!Data {
return try readFn(this.wrapped, count);
pub fn read(this: @This(), count: usize) anyerror!Data {
return readFn(this.wrapped, count);
}
pub fn skip(this: @This(), count: isize) anyerror!void {
skipFn(this.wrapped, count);
pub fn skip(this: @This(), count: anytype) void {
skipFn(this.wrapped, @as(isize, @intCast(count)));
}
pub fn peek(this: @This()) []const u8 {
return peekFn(this.wrapped);
}
pub inline fn readZ(this: @This()) anyerror!Data {
return try readZFn(this.wrapped);
pub fn readZ(this: @This()) anyerror!Data {
return readZFn(this.wrapped);
}
pub fn byte(this: @This()) !u8 {
@@ -220,7 +220,7 @@ pub fn NewReaderWrap(
return data.slice()[0];
}
pub inline fn ensureCapacity(this: @This(), count: usize) anyerror!void {
pub fn ensureCapacity(this: @This(), count: usize) anyerror!void {
if (!ensureCapacityFn(this.wrapped, count)) {
return error.ShortRead;
}
@@ -238,10 +238,18 @@ pub fn NewReaderWrap(
}
pub fn NewReader(comptime Context: type) type {
return NewReaderWrap(Context, Context.markMessageStart, Context.peek, Context.skip, Context.ensureLength, Context.read, Context.readZ);
if (@hasDecl(Context, "is_wrapped")) {
return Context;
}
return NewReaderWrap(Context, Context.markMessageStart, Context.peek, Context.skip, Context.ensureCapacity, Context.read, Context.readZ);
}
pub fn NewWriter(comptime Context: type) type {
if (@hasDecl(Context, "is_wrapped")) {
return Context;
}
return NewWriterWrap(Context, Context.offset, Context.write, Context.pwrite);
}
@@ -249,7 +257,20 @@ fn decoderWrap(comptime Container: type, comptime decodeFn: anytype) type {
return struct {
pub fn decode(this: *Container, context: anytype) anyerror!void {
const Context = @TypeOf(context);
try decodeFn(this, Context, NewReader(Context){ .wrapped = context });
if (@hasDecl(Context, "is_wrapped")) {
try decodeFn(this, Context, context);
} else {
try decodeFn(this, Context, .{ .wrapped = context });
}
}
pub fn decodeAllocator(this: *Container, allocator: std.mem.Allocator, context: anytype) anyerror!void {
const Context = @TypeOf(context);
if (@hasDecl(Context, "is_wrapped")) {
try decodeFn(this, allocator, Context, context);
} else {
try decodeFn(this, allocator, Context, .{ .wrapped = context });
}
}
};
}
@@ -258,7 +279,11 @@ fn writeWrap(comptime Container: type, comptime writeFn: anytype) type {
return struct {
pub fn write(this: *Container, context: anytype) anyerror!void {
const Context = @TypeOf(context);
try writeFn(this, Context, NewWriter(Context){ .wrapped = context });
if (@hasDecl(Context, "is_wrapped")) {
try writeFn(this, Context, context);
} else {
try writeFn(this, Context, .{ .wrapped = context });
}
}
};
}
@@ -413,7 +438,7 @@ pub const HandshakeV10 = struct {
}
// Skip reserved bytes
try reader.skip(10);
reader.skip(10);
// Auth plugin data part 2
const remaining_auth_len = @max(13, auth_plugin_data_len - 8);
@@ -536,7 +561,7 @@ pub const OKPacket = struct {
// Affected rows (length encoded integer)
if (decodeLengthInt(reader.peek())) |result| {
this.affected_rows = result.value;
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
} else {
return error.InvalidOKPacket;
}
@@ -544,7 +569,7 @@ pub const OKPacket = struct {
// Last insert ID (length encoded integer)
if (decodeLengthInt(reader.peek())) |result| {
this.last_insert_id = result.value;
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
} else {
return error.InvalidOKPacket;
}
@@ -565,7 +590,7 @@ pub const OKPacket = struct {
if (decodeLengthInt(reader.peek())) |result| {
const state_data = try reader.read(@intCast(result.value));
this.session_state_changes = state_data;
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
}
}
}
@@ -602,7 +627,7 @@ pub const ErrorPacket = struct {
this.sql_state = sql_state_data.slice()[0..5].*;
} else {
// No SQL state, rewind one byte
try reader.skip(-1);
reader.skip(-1);
}
// Read the error message (rest of packet)
@@ -848,32 +873,32 @@ pub const ColumnDefinition41 = struct {
pub fn decodeInternal(this: *ColumnDefinition41, comptime Context: type, reader: NewReader(Context)) !void {
// Length encoded strings
if (decodeLengthInt(reader.peek())) |result| {
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
this.catalog = try reader.read(@intCast(result.value));
} else return error.InvalidColumnDefinition;
if (decodeLengthInt(reader.peek())) |result| {
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
this.schema = try reader.read(@intCast(result.value));
} else return error.InvalidColumnDefinition;
if (decodeLengthInt(reader.peek())) |result| {
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
this.table = try reader.read(@intCast(result.value));
} else return error.InvalidColumnDefinition;
if (decodeLengthInt(reader.peek())) |result| {
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
this.org_table = try reader.read(@intCast(result.value));
} else return error.InvalidColumnDefinition;
if (decodeLengthInt(reader.peek())) |result| {
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
this.name = try reader.read(@intCast(result.value));
} else return error.InvalidColumnDefinition;
if (decodeLengthInt(reader.peek())) |result| {
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
this.org_name = try reader.read(@intCast(result.value));
} else return error.InvalidColumnDefinition;
@@ -888,7 +913,7 @@ pub const ColumnDefinition41 = struct {
this.decimals = try reader.int(u8);
// Skip filler
try reader.skip(2);
reader.skip(2);
}
pub const decode = decoderWrap(ColumnDefinition41, decodeInternal).decode;
@@ -898,7 +923,7 @@ fn decodeBinaryValue(field_type: types.FieldType, unsigned: bool, comptime Conte
return switch (field_type) {
.MYSQL_TYPE_TINY => blk: {
const val = try reader.byte();
break :blk Value{ .bool = val[0] != 0 };
break :blk Value{ .bool = val != 0 };
},
.MYSQL_TYPE_SHORT => if (unsigned)
Value{ .ushort = try reader.int(u16) }
@@ -915,38 +940,42 @@ fn decodeBinaryValue(field_type: types.FieldType, unsigned: bool, comptime Conte
.MYSQL_TYPE_FLOAT => Value{ .float = @bitCast(try reader.int(u32)) },
.MYSQL_TYPE_DOUBLE => Value{ .double = @bitCast(try reader.int(u64)) },
.MYSQL_TYPE_TIME => switch (try reader.byte()) {
0 => Value{ .null = .{} },
8, 12 => |l| Value{ .time = try Value.Time.fromBinary(reader.read(l)) },
0 => Value{ .null = {} },
8, 12 => |l| Value{ .time = try Value.Time.fromData(&try reader.read(l)) },
else => return error.InvalidBinaryValue,
},
.MYSQL_TYPE_DATE => switch (try reader.byte()) {
0 => Value{ .null = .{} },
4 => Value{ .date = try Value.DateTime.fromBinary(reader.read(4)) },
0 => Value{ .null = {} },
4 => Value{ .date = try Value.DateTime.fromData(&try reader.read(4)) },
else => error.InvalidBinaryValue,
},
.MYSQL_TYPE_DATETIME => switch (try reader.byte()) {
0 => Value{ .null = .{} },
11, 7, 4 => |l| Value{ .date = try Value.DateTime.fromBinary(reader.read(l)) },
0 => Value{ .null = {} },
11, 7, 4 => |l| Value{ .date = try Value.DateTime.fromData(&try reader.read(l)) },
else => error.InvalidBinaryValue,
},
.MYSQL_TYPE_TIMESTAMP => switch (try reader.byte()) {
0 => Value{ .null = .{} },
4, 7 => |l| Value{ .timestamp = try Value.Timestamp.fromBinary(reader.read(l)) },
0 => Value{ .null = {} },
4, 7 => |l| Value{ .timestamp = try Value.Timestamp.fromData(&try reader.read(l)) },
else => error.InvalidBinaryValue,
},
.MYSQL_TYPE_STRING, .MYSQL_TYPE_VARCHAR, .MYSQL_TYPE_VAR_STRING => blk: {
if (decodeLengthInt(reader.peek())) |result| {
reader.skip(result.bytes_read);
const val = try reader.read(@intCast(result.value));
break :blk .{ .string_data = val };
} else return error.InvalidBinaryValue;
},
.MYSQL_TYPE_TINY_BLOB,
.MYSQL_TYPE_MEDIUM_BLOB,
.MYSQL_TYPE_LONG_BLOB,
.MYSQL_TYPE_BLOB,
.MYSQL_TYPE_STRING,
.MYSQL_TYPE_VARCHAR,
.MYSQL_TYPE_VAR_STRING,
.MYSQL_TYPE_JSON,
=> blk: {
if (decodeLengthInt(reader.peek())) |result| {
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
const val = try reader.read(@intCast(result.value));
break :blk .{ .bytes = val };
break :blk .{ .bytes_data = val };
} else return error.InvalidBinaryValue;
},
else => return error.UnsupportedColumnType,
@@ -955,14 +984,14 @@ fn decodeBinaryValue(field_type: types.FieldType, unsigned: bool, comptime Conte
// Result set header packet
pub const ResultSetHeader = struct {
field_count: u64,
field_count: u64 = 0,
extra: ?u64 = null,
pub fn decodeInternal(this: *ResultSetHeader, comptime Context: type, reader: NewReader(Context)) !void {
// Field count (length encoded integer)
if (decodeLengthInt(reader.peek())) |result| {
this.field_count = result.value;
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
} else {
return error.InvalidResultSetHeader;
}
@@ -971,7 +1000,7 @@ pub const ResultSetHeader = struct {
if (reader.peek().len > 0) {
if (decodeLengthInt(reader.peek())) |result| {
this.extra = result.value;
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
}
}
}
@@ -1268,14 +1297,14 @@ pub const Auth = struct {
// Result set packet types
pub const ResultSet = struct {
pub const Header = struct {
field_count: u64,
field_count: u64 = 0,
extra: ?u64 = null,
pub fn decodeInternal(this: *Header, comptime Context: type, reader: NewReader(Context)) !void {
// Field count (length encoded integer)
if (decodeLengthInt(reader.peek())) |result| {
this.field_count = result.value;
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
} else {
return error.InvalidResultSetHeader;
}
@@ -1284,7 +1313,7 @@ pub const ResultSet = struct {
if (reader.peek().len > 0) {
if (decodeLengthInt(reader.peek())) |result| {
this.extra = result.value;
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
}
}
}
@@ -1299,7 +1328,7 @@ pub const ResultSet = struct {
extern fn MySQL__toJSFromRow(*JSC.JSGlobalObject, JSC.JSValue, JSC.JSValue, *anyopaque, usize) JSC.JSValue;
pub fn toJS(this: *Row, structure_value: JSValue, array_value: JSValue, globalObject: *JSC.JSGlobalObject) JSValue {
return MySQL__toJSFromRow(globalObject, structure_value, array_value, this.values, this.columns.len);
return MySQL__toJSFromRow(globalObject, structure_value, array_value, this.values.ptr, this.columns.len);
}
pub fn deinit(this: *Row, allocator: std.mem.Allocator) void {
@@ -1330,12 +1359,12 @@ pub const ResultSet = struct {
for (values) |*value| {
if (decodeLengthInt(reader.peek())) |result| {
try reader.skip(result.bytes_read);
reader.skip(result.bytes_read);
if (result.value == 0xfb) { // NULL value
value.* = .{ .null = {} };
} else {
value.* = .{
.string = try reader.read(@intCast(result.value)),
.string_data = try reader.read(@intCast(result.value)),
};
}
} else {
@@ -1373,18 +1402,18 @@ pub const ResultSet = struct {
const is_null = (null_bitmap.slice()[byte_pos] & (@as(u8, 1) << bit_pos)) != 0;
if (is_null) {
value.* = .{ .empty = {} };
value.* = .{ .null = {} };
continue;
}
const column = this.columns[i];
value.* = try decodeBinaryValue(column.column_type, Context, reader);
value.* = try decodeBinaryValue(column.column_type, column.flags.UNSIGNED, Context, reader);
}
this.values = values;
}
pub const decode = decoderWrap(Row, decodeInternal).decode;
pub const decode = decoderWrap(Row, decodeInternal).decodeAllocator;
};
};
@@ -1392,7 +1421,7 @@ pub const ResultSet = struct {
pub const PreparedStatement = struct {
pub const Prepare = struct {
command: CommandType = .COM_STMT_PREPARE,
query: Data,
query: Data = .{ .empty = {} },
pub fn deinit(this: *Prepare) void {
this.query.deinit();
@@ -1441,7 +1470,7 @@ pub const PreparedStatement = struct {
/// Whether to send parameter types. Set to true for first execution, false for subsequent executions
new_params_bind_flag: bool = true,
/// Parameter values to bind to the prepared statement
params: []const Data = &[_]Data{},
params: []Data = &[_]Data{},
/// Types of each parameter in the prepared statement
param_types: []const types.FieldType = &[_]types.FieldType{},
@@ -1504,7 +1533,7 @@ pub const PreparedStatement = struct {
pub const Close = struct {
command: CommandType = .COM_STMT_CLOSE,
statement_id: u32,
statement_id: u32 = 0,
pub fn writeInternal(this: *const Close, comptime Context: type, writer: NewWriter(Context)) !void {
try writer.int1(@intFromEnum(this.command));
@@ -1516,7 +1545,7 @@ pub const PreparedStatement = struct {
pub const Reset = struct {
command: CommandType = .COM_STMT_RESET,
statement_id: u32,
statement_id: u32 = 0,
pub fn writeInternal(this: *const Reset, comptime Context: type, writer: NewWriter(Context)) !void {
try writer.int1(@intFromEnum(this.command));

View File

@@ -183,7 +183,9 @@ pub const Value = union(enum) {
double: f64,
string: JSC.ZigString.Slice,
string_data: Data,
bytes: JSC.ZigString.Slice,
bytes_data: Data,
date: DateTime,
timestamp: Timestamp,
time: Time,
@@ -191,7 +193,8 @@ pub const Value = union(enum) {
pub fn deinit(this: *Value, allocator: std.mem.Allocator) void {
switch (this.*) {
inline .string, .bytes => |*slice| slice.deinit(allocator),
inline .string, .bytes => |*slice| slice.deinit(),
inline .string_data, .bytes_data => |*data| data.deinit(),
.decimal => |*decimal| decimal.deinit(allocator),
else => {},
}
@@ -219,6 +222,7 @@ pub const Value = union(enum) {
stream.pos = d.toBinary(field_type, &buffer);
},
.decimal => |dec| return try dec.toBinary(field_type),
.string_data, .bytes_data => |data| return data,
.string, .bytes => |slice| return if (slice.len > 0)
Data{ .temporary = slice.slice() }
else
@@ -285,6 +289,10 @@ pub const Value = union(enum) {
seconds: u32,
microseconds: u24,
pub fn fromData(data: *const Data) !Timestamp {
return fromBinary(data.slice());
}
pub fn fromBinary(val: []const u8) Timestamp {
return .{
// Bytes 0-3: [seconds] (32-bit little-endian unsigned integer)
@@ -348,6 +356,10 @@ pub const Value = union(enum) {
second: u8 = 0,
microsecond: u32 = 0,
pub fn fromData(data: *const Data) !DateTime {
return fromBinary(data.slice());
}
pub fn fromBinaryDate(val: []const u8) DateTime {
return .{
.year = std.mem.readInt(u16, val[0..2], .little),
@@ -532,6 +544,10 @@ pub const Value = union(enum) {
return total_ms;
}
pub fn fromData(data: *const Data) !Time {
return fromBinary(data.slice());
}
pub fn fromBinary(val: []const u8) Time {
if (val.len == 0) {
return Time{};
@@ -542,14 +558,14 @@ pub const Value = union(enum) {
if (length >= 8) {
time.negative = val[1] != 0;
time.days = std.mem.readInt(.little, val[2..6]);
time.days = std.mem.readInt(u32, val[2..6], .little);
time.hours = val[6];
time.minutes = val[7];
time.seconds = val[8];
}
if (length > 8) {
time.microseconds = std.mem.readInt(.little, val[9..13]);
time.microseconds = std.mem.readInt(u32, val[9..13], .little);
}
return time;
@@ -584,7 +600,7 @@ pub const Value = union(enum) {
return 9;
} else {
buffer[0] = 12; // length
std.mem.writeInt(u32, buffer[9..], this.microseconds, .little);
std.mem.writeInt(u32, buffer[9..][0..4], this.microseconds, .little);
return 12;
}
},
@@ -629,17 +645,27 @@ pub const Value = union(enum) {
_ = field_type; // autofix
bun.todoPanic(@src(), "Decimal.toBinary not implemented", .{});
}
pub fn fromData(data: *const Data) !Decimal {
return fromBinary(data.slice());
}
pub fn fromBinary(val: []const u8) Decimal {
_ = val; // autofix
// TODO: handle overflow
bun.todoPanic(@src(), "Decimal.fromBinary not implemented", .{});
}
};
pub fn toJS(this: *const Value, globalObject: *JSC.JSGlobalObject) JSValue {
return switch (this.*) {
.null => JSValue.jsNull(),
.bool => |b| JSValue.jsBoolean(b),
.string => |*str| {
inline .string, .string_data => |*str| {
var out = bun.String.createUTF8(str.slice());
return out.transferToJS(globalObject);
},
.bytes => JSC.ArrayBuffer.createBuffer(globalObject, this.bytes.slice()),
inline .bytes, .bytes_data => |*data| JSC.ArrayBuffer.createBuffer(globalObject, data.slice()),
inline .long, .int, .float, .double, .short, .ushort, .uint, .ulong => |t| JSValue.jsNumber(t),
inline .timestamp, .date, .time, .decimal => |*d| d.toJS(globalObject),
};