1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum FrontendMessage {
8 Startup,
10 PasswordMessage,
12 SASLInitialResponse,
14 SASLResponse,
16 Parse,
18 Bind,
20 Describe,
22 Execute,
24 Sync,
26 Close,
28 Query,
30 Terminate,
32 Flush,
34 CopyData,
36 CopyDone,
38 CopyFail,
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44#[repr(u8)]
45pub enum BackendTag {
46 AuthenticationRequest = b'R',
47 ParameterStatus = b'S',
48 BackendKeyData = b'K',
49 ReadyForQuery = b'Z',
50 RowDescription = b'T',
51 DataRow = b'D',
52 CommandComplete = b'C',
53 ErrorResponse = b'E',
54 NoticeResponse = b'N',
55 ParseComplete = b'1',
56 BindComplete = b'2',
57 CloseComplete = b'3',
58 NoData = b'n',
59 ParameterDescription = b't',
60 EmptyQueryResponse = b'I',
61 NotificationResponse = b'A',
62 CopyInResponse = b'G',
63 CopyOutResponse = b'H',
64 CopyDone = b'c',
65 CopyData = b'd',
66 NegotiateProtocolVersion = b'v',
67 Unknown = 0,
68}
69
70impl From<u8> for BackendTag {
71 fn from(b: u8) -> Self {
72 match b {
73 b'R' => BackendTag::AuthenticationRequest,
74 b'S' => BackendTag::ParameterStatus,
75 b'K' => BackendTag::BackendKeyData,
76 b'Z' => BackendTag::ReadyForQuery,
77 b'T' => BackendTag::RowDescription,
78 b'D' => BackendTag::DataRow,
79 b'C' => BackendTag::CommandComplete,
80 b'E' => BackendTag::ErrorResponse,
81 b'N' => BackendTag::NoticeResponse,
82 b'1' => BackendTag::ParseComplete,
83 b'2' => BackendTag::BindComplete,
84 b'3' => BackendTag::CloseComplete,
85 b'n' => BackendTag::NoData,
86 b't' => BackendTag::ParameterDescription,
87 b'I' => BackendTag::EmptyQueryResponse,
88 b'A' => BackendTag::NotificationResponse,
89 b'G' => BackendTag::CopyInResponse,
90 b'H' => BackendTag::CopyOutResponse,
91 b'c' => BackendTag::CopyDone,
92 b'd' => BackendTag::CopyData,
93 b'v' => BackendTag::NegotiateProtocolVersion,
94 _ => BackendTag::Unknown,
95 }
96 }
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub enum AuthType {
102 Ok = 0,
103 CleartextPassword = 3,
104 MD5Password = 5,
105 SASLInit = 10,
106 SASLContinue = 11,
107 SASLFinal = 12,
108}
109
110impl AuthType {
111 pub fn from_i32(v: i32) -> Option<Self> {
112 match v {
113 0 => Some(AuthType::Ok),
114 3 => Some(AuthType::CleartextPassword),
115 5 => Some(AuthType::MD5Password),
116 10 => Some(AuthType::SASLInit),
117 11 => Some(AuthType::SASLContinue),
118 12 => Some(AuthType::SASLFinal),
119 _ => None,
120 }
121 }
122}
123
124#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126pub enum TransactionStatus {
127 Idle,
129 InTransaction,
131 Failed,
133}
134
135impl From<u8> for TransactionStatus {
136 fn from(b: u8) -> Self {
137 match b {
138 b'T' => TransactionStatus::InTransaction,
139 b'E' => TransactionStatus::Failed,
140 _ => TransactionStatus::Idle,
141 }
142 }
143}
144
145#[derive(Debug, Clone, Copy)]
147pub enum DescribeTarget {
148 Statement,
149 Portal,
150}
151
152#[derive(Debug, Clone, Copy)]
154pub enum CloseTarget {
155 Statement,
156 Portal,
157}
158
159#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161pub enum FormatCode {
162 Text = 0,
163 Binary = 1,
164}
165
166impl From<i16> for FormatCode {
167 fn from(v: i16) -> Self {
168 if v == 1 {
169 FormatCode::Binary
170 } else {
171 FormatCode::Text
172 }
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
183 fn test_backend_tag_auth() {
184 assert_eq!(BackendTag::from(b'R'), BackendTag::AuthenticationRequest);
185 }
186
187 #[test]
188 fn test_backend_tag_parameter_status() {
189 assert_eq!(BackendTag::from(b'S'), BackendTag::ParameterStatus);
190 }
191
192 #[test]
193 fn test_backend_tag_backend_key_data() {
194 assert_eq!(BackendTag::from(b'K'), BackendTag::BackendKeyData);
195 }
196
197 #[test]
198 fn test_backend_tag_ready_for_query() {
199 assert_eq!(BackendTag::from(b'Z'), BackendTag::ReadyForQuery);
200 }
201
202 #[test]
203 fn test_backend_tag_row_description() {
204 assert_eq!(BackendTag::from(b'T'), BackendTag::RowDescription);
205 }
206
207 #[test]
208 fn test_backend_tag_data_row() {
209 assert_eq!(BackendTag::from(b'D'), BackendTag::DataRow);
210 }
211
212 #[test]
213 fn test_backend_tag_command_complete() {
214 assert_eq!(BackendTag::from(b'C'), BackendTag::CommandComplete);
215 }
216
217 #[test]
218 fn test_backend_tag_error_response() {
219 assert_eq!(BackendTag::from(b'E'), BackendTag::ErrorResponse);
220 }
221
222 #[test]
223 fn test_backend_tag_notice_response() {
224 assert_eq!(BackendTag::from(b'N'), BackendTag::NoticeResponse);
225 }
226
227 #[test]
228 fn test_backend_tag_parse_complete() {
229 assert_eq!(BackendTag::from(b'1'), BackendTag::ParseComplete);
230 }
231
232 #[test]
233 fn test_backend_tag_bind_complete() {
234 assert_eq!(BackendTag::from(b'2'), BackendTag::BindComplete);
235 }
236
237 #[test]
238 fn test_backend_tag_close_complete() {
239 assert_eq!(BackendTag::from(b'3'), BackendTag::CloseComplete);
240 }
241
242 #[test]
243 fn test_backend_tag_no_data() {
244 assert_eq!(BackendTag::from(b'n'), BackendTag::NoData);
245 }
246
247 #[test]
248 fn test_backend_tag_parameter_description() {
249 assert_eq!(BackendTag::from(b't'), BackendTag::ParameterDescription);
250 }
251
252 #[test]
253 fn test_backend_tag_empty_query() {
254 assert_eq!(BackendTag::from(b'I'), BackendTag::EmptyQueryResponse);
255 }
256
257 #[test]
258 fn test_backend_tag_notification() {
259 assert_eq!(BackendTag::from(b'A'), BackendTag::NotificationResponse);
260 }
261
262 #[test]
263 fn test_backend_tag_copy_in() {
264 assert_eq!(BackendTag::from(b'G'), BackendTag::CopyInResponse);
265 }
266
267 #[test]
268 fn test_backend_tag_copy_out() {
269 assert_eq!(BackendTag::from(b'H'), BackendTag::CopyOutResponse);
270 }
271
272 #[test]
273 fn test_backend_tag_copy_done() {
274 assert_eq!(BackendTag::from(b'c'), BackendTag::CopyDone);
275 }
276
277 #[test]
278 fn test_backend_tag_copy_data_lowercase() {
279 assert_eq!(BackendTag::from(b'd'), BackendTag::CopyData);
280 }
281
282 #[test]
283 fn test_backend_tag_negotiate_protocol() {
284 assert_eq!(BackendTag::from(b'v'), BackendTag::NegotiateProtocolVersion);
285 }
286
287 #[test]
288 fn test_backend_tag_unknown_byte() {
289 assert_eq!(BackendTag::from(0xFF), BackendTag::Unknown);
290 }
291
292 #[test]
293 fn test_backend_tag_unknown_zero() {
294 assert_eq!(BackendTag::from(0x00), BackendTag::Unknown);
295 }
296
297 #[test]
298 fn test_backend_tag_debug_format() {
299 let tag = BackendTag::ReadyForQuery;
300 let s = format!("{:?}", tag);
301 assert_eq!(s, "ReadyForQuery");
302 }
303
304 #[test]
305 fn test_backend_tag_equality() {
306 assert_eq!(BackendTag::from(b'Z'), BackendTag::ReadyForQuery);
307 assert_ne!(BackendTag::from(b'Z'), BackendTag::ErrorResponse);
308 }
309
310 #[test]
311 fn test_backend_tag_repr_values() {
312 assert_eq!(BackendTag::AuthenticationRequest as u8, b'R');
314 assert_eq!(BackendTag::ReadyForQuery as u8, b'Z');
315 assert_eq!(BackendTag::ErrorResponse as u8, b'E');
316 assert_eq!(BackendTag::DataRow as u8, b'D');
317 assert_eq!(BackendTag::CommandComplete as u8, b'C');
318 }
319
320 #[test]
323 fn test_tx_status_idle_from_i() {
324 assert_eq!(TransactionStatus::from(b'I'), TransactionStatus::Idle);
325 }
326
327 #[test]
328 fn test_tx_status_in_transaction() {
329 assert_eq!(
330 TransactionStatus::from(b'T'),
331 TransactionStatus::InTransaction
332 );
333 }
334
335 #[test]
336 fn test_tx_status_failed() {
337 assert_eq!(TransactionStatus::from(b'E'), TransactionStatus::Failed);
338 }
339
340 #[test]
341 fn test_tx_status_unknown_defaults_idle() {
342 assert_eq!(TransactionStatus::from(0xFF), TransactionStatus::Idle);
344 assert_eq!(TransactionStatus::from(b'X'), TransactionStatus::Idle);
345 }
346
347 #[test]
348 fn test_tx_status_debug() {
349 assert_eq!(format!("{:?}", TransactionStatus::Idle), "Idle");
350 assert_eq!(
351 format!("{:?}", TransactionStatus::InTransaction),
352 "InTransaction"
353 );
354 assert_eq!(format!("{:?}", TransactionStatus::Failed), "Failed");
355 }
356
357 #[test]
358 fn test_tx_status_eq() {
359 assert_eq!(TransactionStatus::Idle, TransactionStatus::Idle);
360 assert_ne!(TransactionStatus::Idle, TransactionStatus::InTransaction);
361 }
362
363 #[test]
366 fn test_auth_type_ok() {
367 assert_eq!(AuthType::from_i32(0), Some(AuthType::Ok));
368 }
369
370 #[test]
371 fn test_auth_type_cleartext() {
372 assert_eq!(AuthType::from_i32(3), Some(AuthType::CleartextPassword));
373 }
374
375 #[test]
376 fn test_auth_type_md5() {
377 assert_eq!(AuthType::from_i32(5), Some(AuthType::MD5Password));
378 }
379
380 #[test]
381 fn test_auth_type_sasl_init() {
382 assert_eq!(AuthType::from_i32(10), Some(AuthType::SASLInit));
383 }
384
385 #[test]
386 fn test_auth_type_sasl_continue() {
387 assert_eq!(AuthType::from_i32(11), Some(AuthType::SASLContinue));
388 }
389
390 #[test]
391 fn test_auth_type_sasl_final() {
392 assert_eq!(AuthType::from_i32(12), Some(AuthType::SASLFinal));
393 }
394
395 #[test]
396 fn test_auth_type_unknown_returns_none() {
397 assert_eq!(AuthType::from_i32(1), None);
398 assert_eq!(AuthType::from_i32(99), None);
399 assert_eq!(AuthType::from_i32(-1), None);
400 }
401
402 #[test]
405 fn test_format_code_text_from_zero() {
406 assert_eq!(FormatCode::from(0i16), FormatCode::Text);
407 }
408
409 #[test]
410 fn test_format_code_binary_from_one() {
411 assert_eq!(FormatCode::from(1i16), FormatCode::Binary);
412 }
413
414 #[test]
415 fn test_format_code_unknown_defaults_text() {
416 assert_eq!(FormatCode::from(2i16), FormatCode::Text);
418 assert_eq!(FormatCode::from(-1i16), FormatCode::Text);
419 assert_eq!(FormatCode::from(99i16), FormatCode::Text);
420 }
421
422 #[test]
423 fn test_format_code_values() {
424 assert_eq!(FormatCode::Text as i16, 0);
425 assert_eq!(FormatCode::Binary as i16, 1);
426 }
427
428 #[test]
429 fn test_format_code_eq() {
430 assert_eq!(FormatCode::Text, FormatCode::Text);
431 assert_ne!(FormatCode::Text, FormatCode::Binary);
432 }
433
434 #[test]
437 fn test_all_known_backend_tags_roundtrip() {
438 let pairs: &[(u8, BackendTag)] = &[
439 (b'R', BackendTag::AuthenticationRequest),
440 (b'S', BackendTag::ParameterStatus),
441 (b'K', BackendTag::BackendKeyData),
442 (b'Z', BackendTag::ReadyForQuery),
443 (b'T', BackendTag::RowDescription),
444 (b'D', BackendTag::DataRow),
445 (b'C', BackendTag::CommandComplete),
446 (b'E', BackendTag::ErrorResponse),
447 (b'N', BackendTag::NoticeResponse),
448 (b'1', BackendTag::ParseComplete),
449 (b'2', BackendTag::BindComplete),
450 (b'3', BackendTag::CloseComplete),
451 (b'n', BackendTag::NoData),
452 (b't', BackendTag::ParameterDescription),
453 (b'I', BackendTag::EmptyQueryResponse),
454 (b'A', BackendTag::NotificationResponse),
455 (b'G', BackendTag::CopyInResponse),
456 (b'H', BackendTag::CopyOutResponse),
457 (b'c', BackendTag::CopyDone),
458 (b'd', BackendTag::CopyData),
459 (b'v', BackendTag::NegotiateProtocolVersion),
460 ];
461 for &(byte, ref expected) in pairs {
462 let got = BackendTag::from(byte);
463 assert_eq!(
464 &got, expected,
465 "byte {:#04x} should map to {:?}",
466 byte, expected
467 );
468 }
469 }
470}