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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
// Copyright (c) 2026, Salesforce, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! Frontend (client-to-server) messages.
//!
//! Each function in this module writes a single `PostgreSQL` wire protocol
//! message into a [`BytesMut`] buffer. All structural fields (tags, lengths,
//! counts) are written in **`BigEndian`** per the `PostgreSQL` specification.
//!
//! The functions are intentionally stateless -- they append bytes to a buffer
//! and do not manage connection state. The connection layer in `hyper-client`
//! is responsible for sequencing messages correctly (e.g. Parse/Bind/Execute
//! followed by Sync).
//!
//! # Attribution
//!
//! Portions of this module were adapted from
//! [`postgres-protocol`](https://github.com/sfackler/rust-postgres)'s
//! `message/frontend.rs` (Copyright (c) 2016 Steven Fackler, MIT or
//! Apache-2.0). Adapted material includes the PostgreSQL v3.0
//! protocol-version literal (`196608`, `(3 << 16) | 0`), the startup-message
//! framing layout, and the `msg_len` helper. Hyper-specific changes added
//! on top include performance work and Hyper-specific message variants.
//! See the `NOTICE` file at the repo root for the full upstream copyright
//! and reproduced license text.
use ;
use io;
use crateOid;
/// Narrows a `usize` length to the `PostgreSQL` wire-protocol `i32` length prefix.
///
/// Panics on overflow. The `PostgreSQL` protocol caps individual messages at
/// `i32::MAX` bytes (~2 GiB); any single string, query, or byte slice exceeding
/// that is a programming error, not a runtime-recoverable condition. Per the
/// M-PANIC-ON-BUG guideline, we panic rather than threading a `Result` through
/// every wire-format helper.
/// Narrows a `usize` count to the `PostgreSQL` wire-protocol 16-bit parameter /
/// format count.
///
/// The wire field is `Int16` (signed on the wire, but values `0..=65_535` are
/// legal — the high bit is a permitted value, not a sign). We go through `u16`
/// first to trap genuine overflow, then bit-reinterpret to `i16` so
/// [`bytes::BufMut::put_i16`] writes the expected `BigEndian` representation.
///
/// Panics if the count exceeds `65_535`. In practice Hyper/PostgreSQL cap this
/// far lower (1600 parameters per query), so overflow is a programming error.
/// Writes a startup message to the buffer.
///
/// The startup message establishes the connection and sets initial parameters.
/// This is the first message sent by the client after establishing a TCP connection.
///
/// # Arguments
///
/// * `parameters` - Key-value pairs of connection parameters (e.g., "user", "database")
/// * `buf` - Buffer to write the message to
///
/// # Errors
///
/// Currently infallible — always returns `Ok(())`. The `io::Result` return
/// type is preserved for forward compatibility so that future validation
/// (e.g. parameter-length checks) can surface errors without a breaking
/// signature change.
///
/// # Panics
///
/// Panics via `msg_len` if the total encoded message length exceeds
/// `i32::MAX` bytes (~2 GiB). PostgreSQL caps messages at that size, so
/// exceeding it is a programming error.
/// Writes a password message (for authentication).
///
/// Sent in response to `AuthenticationCleartextPassword` or after MD5 hashing.
///
/// # Arguments
///
/// * `password` - The password to send (plaintext or MD5 hash)
/// * `buf` - Buffer to write the message to
///
/// # Errors
///
/// Currently infallible — always returns `Ok(())`. The `io::Result` return
/// type is preserved for forward compatibility.
///
/// # Panics
///
/// Panics via `msg_len` if `password.len()` exceeds `i32::MAX` bytes.
/// Writes a SASL initial response message.
///
/// Used to initiate SASL authentication (e.g., SCRAM-SHA-256).
/// Sent in response to `AuthenticationSasl` message.
///
/// # Arguments
///
/// * `mechanism` - The SASL mechanism name to use
/// * `data` - Initial client response data (may be empty)
/// * `buf` - Buffer to write the message to
///
/// # Errors
///
/// Currently infallible — always returns `Ok(())`. The `io::Result` return
/// type is preserved for forward compatibility.
///
/// # Panics
///
/// Panics via `msg_len` if `mechanism.len()` or `data.len()` exceeds
/// `i32::MAX` bytes.
/// Writes a SASL response message.
///
/// Used to continue SASL authentication exchange.
/// Sent in response to `AuthenticationSaslContinue` messages.
///
/// # Arguments
///
/// * `data` - Client response data for this authentication step
/// * `buf` - Buffer to write the message to
///
/// # Errors
///
/// Currently infallible — always returns `Ok(())`. The `io::Result` return
/// type is preserved for forward compatibility.
///
/// # Panics
///
/// Panics via `msg_len` if `data.len()` exceeds `i32::MAX` bytes.
/// Writes a simple query message.
///
/// Executes a SQL query directly without using prepared statements.
/// The server will respond with `RowDescription`, `DataRow`, `CommandComplete`, etc.
///
/// # Arguments
///
/// * `query` - SQL query string (null-terminated)
/// * `buf` - Buffer to write the message to
///
/// # Errors
///
/// Currently infallible — always returns `Ok(())`. The `io::Result` return
/// type is preserved for forward compatibility.
///
/// # Panics
///
/// Panics via `msg_len` if `query.len()` exceeds `i32::MAX` bytes
/// (PostgreSQL's per-message cap).
/// Writes a parse message (prepare statement).
///
/// Prepares a SQL statement for later execution. The server responds with
/// `ParseComplete` and may send `ParameterDescription`.
///
/// # Arguments
///
/// * `name` - Statement name (null-terminated, empty string for unnamed)
/// * `query` - SQL query string with parameter placeholders ($1, $2, etc.)
/// * `param_types` - OIDs of parameter types (empty if types should be inferred)
/// * `buf` - Buffer to write the message to
///
/// # Errors
///
/// Currently infallible — always returns `Ok(())`. The `io::Result` return
/// type is preserved for forward compatibility.
///
/// # Panics
///
/// - Panics via `msg_len` if `name.len()`, `query.len()`, or the encoded
/// message length exceeds `i32::MAX` bytes.
/// - Panics via `msg_count` if `param_types.len()` exceeds `u16::MAX`
/// (65 535). PostgreSQL caps parameters per query at 1 600, so overflow
/// is a programming error.
/// Writes a bind message.
///
/// Binds parameter values to a prepared statement, creating a portal.
/// The server responds with `BindComplete`.
///
/// # Arguments
///
/// * `portal` - Portal name (null-terminated, empty string for unnamed)
/// * `statement` - Statement name (from Parse message)
/// * `param_formats` - Format codes for each parameter (0 = text, 1 = binary)
/// * `params` - Parameter values (None for NULL)
/// * `result_formats` - Format codes for result columns (0 = text, 1 = binary)
/// * `buf` - Buffer to write the message to
///
/// # Errors
///
/// Currently infallible — always returns `Ok(())`. The `io::Result` return
/// type is preserved for forward compatibility.
///
/// # Panics
///
/// - Panics via `msg_len` if any string length, parameter length, or the
/// total encoded message length exceeds `i32::MAX` bytes.
/// - Panics via `msg_count` if `param_formats.len()`, `params.len()`, or
/// `result_formats.len()` exceeds `u16::MAX` (65 535).
/// Writes a describe message.
///
/// Requests metadata about a prepared statement or portal.
/// The server responds with `RowDescription` or `ParameterDescription`.
///
/// # Arguments
///
/// * `kind` - 'S' for statement, 'P' for portal
/// * `name` - Statement or portal name (null-terminated, empty string for unnamed)
/// * `buf` - Buffer to write the message to
///
/// # Errors
///
/// Currently infallible — always returns `Ok(())`. The `io::Result` return
/// type is preserved for forward compatibility.
///
/// # Panics
///
/// Panics via `msg_len` if `name.len()` exceeds `i32::MAX` bytes.
/// Writes an execute message.
///
/// Executes a portal (bound statement). The server responds with `DataRow`
/// messages and `CommandComplete`. Use 0 for `max_rows` to fetch all rows.
///
/// # Arguments
///
/// * `portal` - Portal name (null-terminated, empty string for unnamed)
/// * `max_rows` - Maximum number of rows to return (0 = unlimited)
/// * `buf` - Buffer to write the message to
///
/// # Errors
///
/// Currently infallible — always returns `Ok(())`. The `io::Result` return
/// type is preserved for forward compatibility.
///
/// # Panics
///
/// Panics via `msg_len` if `portal.len()` exceeds `i32::MAX` bytes.
/// Writes a sync message.
///
/// Forces the server to process all pending messages and respond with `ReadyForQuery`.
/// Should be sent after completing a query sequence (Parse/Bind/Execute).
/// Writes a flush message.
///
/// Requests that the server flush its output buffer.
/// The server will send any pending messages but does not send a response.
/// Writes a close message.
///
/// Closes a prepared statement or portal. The server responds with `CloseComplete`.
///
/// # Arguments
///
/// * `kind` - 'S' for statement, 'P' for portal
/// * `name` - Statement or portal name (null-terminated, empty string for unnamed)
/// * `buf` - Buffer to write the message to
///
/// # Errors
///
/// Currently infallible — always returns `Ok(())`. The `io::Result` return
/// type is preserved for forward compatibility.
///
/// # Panics
///
/// Panics via `msg_len` if `name.len()` exceeds `i32::MAX` bytes.
/// Writes a terminate message.
///
/// Closes the connection gracefully. The server closes the connection
/// after receiving this message. No response is sent.
/// Writes a cancel request.
///
/// Cancels a running query. This is sent on a separate connection from
/// the main connection. The server does not send a response.
///
/// # Arguments
///
/// * `process_id` - Backend process ID (from `BackendKeyData` message)
/// * `secret_key` - Secret key (from `BackendKeyData` message)
/// * `buf` - Buffer to write the message to
/// Writes a copy data message.
///
/// Sends a chunk of COPY data to the server during COPY IN operation.
/// The data format depends on the COPY format (text or binary).
///
/// # Arguments
///
/// * `data` - COPY data bytes
/// * `buf` - Buffer to write the message to
/// Writes a copy done message.
///
/// Indicates that all COPY data has been sent (end of COPY IN operation).
/// The server responds with `CommandComplete`.
/// Writes a copy fail message.
///
/// Aborts a COPY IN operation with an error message.
/// The server responds with `ErrorResponse`.
///
/// # Arguments
///
/// * `message` - Error message explaining why COPY failed
/// * `buf` - Buffer to write the message to