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
use super::new_reader::{NewReader, ReaderContext};
use crate::shared::Data;
pub struct ErrorPacket {
pub header: u8,
pub error_code: u16,
pub sql_state_marker: Option<u8>,
pub sql_state: Option<[u8; 5]>,
pub error_message: Data,
}
impl Default for ErrorPacket {
fn default() -> Self {
Self {
header: 0xff,
error_code: 0,
sql_state_marker: None,
sql_state: None,
error_message: Data::empty(),
}
}
}
// Zig `deinit` only freed `error_message`; `Data: Drop` handles that automatically.
pub struct MySQLErrorOptions {
// TODO(port): verify lifetime — Zig `[]const u8` field with no deinit; assuming static literal
pub code: &'static [u8],
pub errno: Option<u16>,
pub sql_state: Option<[u8; 5]>,
}
// No `impl Default` — Zig `code: []const u8` has no default, so `.{}` is invalid there too.
// `createMySQLError` lives in bun_sql_jsc::mysql::protocol::error_packet_jsc — *_jsc alias deleted.
impl ErrorPacket {
pub fn decode_internal<Context: ReaderContext>(
&mut self,
reader: NewReader<Context>,
) -> Result<(), bun_core::Error> {
// TODO(port): narrow error set
self.header = reader.int::<u8>()?;
if self.header != 0xff {
return Err(bun_core::err!("InvalidErrorPacket"));
}
self.error_code = reader.int::<u16>()?;
// Check if we have a SQL state marker
let next_byte = reader.int::<u8>()?;
if next_byte == b'#' {
self.sql_state_marker = Some(b'#');
let sql_state_data = reader.read(5)?;
// `defer sql_state_data.deinit()` — Drop handles it.
self.sql_state = Some(
sql_state_data.slice()[0..5]
.try_into()
.expect("unreachable"),
);
} else {
// No SQL state, rewind one byte
reader.skip(-1);
}
// Read the error message (rest of packet)
// PORT NOTE: reshaped for borrowck — capture peek().len() before mut call
let remaining = reader.peek().len();
self.error_message = reader.read(remaining)?;
Ok(())
}
}
// Zig `decoderWrap(@This(), ...)` — see Decode trait in src/sql/mysql/protocol/NewReader.rs
pub fn decode<Context: ReaderContext>(
this: &mut ErrorPacket,
reader: NewReader<Context>,
) -> Result<(), bun_core::Error> {
this.decode_internal(reader)
}
// `toJS` lives in bun_sql_jsc::mysql::protocol::error_packet_jsc — *_jsc alias deleted.
// ported from: src/sql/mysql/protocol/ErrorPacket.zig