1use auto_impl::auto_impl;
2
3use crate::constant::ColumnType;
4use crate::error::Result;
5use crate::protocol::primitive::*;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11#[repr(u8)]
12pub enum ParamIndicator {
13 None = 0,
15 Null = 1,
17 Default = 2,
19 Ignore = 3,
21}
22
23pub trait Param {
24 fn is_null(&self) -> bool;
25 fn encode_type(&self, out: &mut Vec<u8>);
26 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()>;
27}
28
29pub trait TypedParam {
30 fn is_null(&self) -> bool {
31 false
32 }
33 fn encode_type(out: &mut Vec<u8>);
34 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()>;
35}
36
37impl TypedParam for i8 {
38 fn encode_type(out: &mut Vec<u8>) {
39 out.push(ColumnType::MYSQL_TYPE_TINY as u8);
40 out.push(0x00);
41 }
42
43 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
44 write_int_1(out, *self as u8);
45 Ok(())
46 }
47}
48
49impl TypedParam for i16 {
50 fn encode_type(out: &mut Vec<u8>) {
51 out.push(ColumnType::MYSQL_TYPE_SHORT as u8);
52 out.push(0x00);
53 }
54
55 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
56 write_int_2(out, *self as u16);
57 Ok(())
58 }
59}
60
61impl TypedParam for i32 {
62 fn encode_type(out: &mut Vec<u8>) {
63 out.push(ColumnType::MYSQL_TYPE_LONG as u8);
64 out.push(0x00);
65 }
66
67 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
68 write_int_4(out, *self as u32);
69 Ok(())
70 }
71}
72
73impl TypedParam for i64 {
74 fn encode_type(out: &mut Vec<u8>) {
75 out.push(ColumnType::MYSQL_TYPE_LONGLONG as u8);
76 out.push(0x00);
77 }
78
79 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
80 write_int_8(out, *self as u64);
81 Ok(())
82 }
83}
84
85impl TypedParam for u8 {
86 fn encode_type(out: &mut Vec<u8>) {
87 out.push(ColumnType::MYSQL_TYPE_TINY as u8);
88 out.push(0x80);
89 }
90
91 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
92 write_int_1(out, *self);
93 Ok(())
94 }
95}
96
97impl TypedParam for u16 {
98 fn encode_type(out: &mut Vec<u8>) {
99 out.push(ColumnType::MYSQL_TYPE_SHORT as u8);
100 out.push(0x80);
101 }
102
103 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
104 write_int_2(out, *self);
105 Ok(())
106 }
107}
108
109impl TypedParam for u32 {
110 fn encode_type(out: &mut Vec<u8>) {
111 out.push(ColumnType::MYSQL_TYPE_LONG as u8);
112 out.push(0x80);
113 }
114
115 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
116 write_int_4(out, *self);
117 Ok(())
118 }
119}
120
121impl TypedParam for u64 {
122 fn encode_type(out: &mut Vec<u8>) {
123 out.push(ColumnType::MYSQL_TYPE_LONGLONG as u8);
124 out.push(0x80);
125 }
126
127 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
128 write_int_8(out, *self);
129 Ok(())
130 }
131}
132
133impl TypedParam for f32 {
134 fn encode_type(out: &mut Vec<u8>) {
135 out.push(ColumnType::MYSQL_TYPE_FLOAT as u8);
136 out.push(0x00);
137 }
138
139 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
140 write_int_4(out, self.to_bits());
141 Ok(())
142 }
143}
144
145impl TypedParam for f64 {
146 fn encode_type(out: &mut Vec<u8>) {
147 out.push(ColumnType::MYSQL_TYPE_DOUBLE as u8);
148 out.push(0x00);
149 }
150
151 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
152 write_int_8(out, self.to_bits());
153 Ok(())
154 }
155}
156
157impl TypedParam for &str {
158 fn encode_type(out: &mut Vec<u8>) {
159 out.push(ColumnType::MYSQL_TYPE_VAR_STRING as u8);
160 out.push(0x00);
161 }
162
163 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
164 write_string_lenenc(out, self);
165 Ok(())
166 }
167}
168
169impl TypedParam for String {
170 fn encode_type(out: &mut Vec<u8>) {
171 out.push(ColumnType::MYSQL_TYPE_VAR_STRING as u8);
172 out.push(0x00);
173 }
174
175 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
176 write_string_lenenc(out, self);
177 Ok(())
178 }
179}
180
181impl TypedParam for &String {
182 fn encode_type(out: &mut Vec<u8>) {
183 out.push(ColumnType::MYSQL_TYPE_VAR_STRING as u8);
184 out.push(0x00);
185 }
186
187 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
188 write_string_lenenc(out, self);
189 Ok(())
190 }
191}
192
193impl TypedParam for &[u8] {
194 fn encode_type(out: &mut Vec<u8>) {
195 out.push(ColumnType::MYSQL_TYPE_BLOB as u8);
196 out.push(0x00);
197 }
198
199 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
200 write_bytes_lenenc(out, self);
201 Ok(())
202 }
203}
204
205impl TypedParam for Vec<u8> {
206 fn encode_type(out: &mut Vec<u8>) {
207 out.push(ColumnType::MYSQL_TYPE_BLOB as u8);
208 out.push(0x00);
209 }
210
211 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
212 write_bytes_lenenc(out, self);
213 Ok(())
214 }
215}
216
217impl TypedParam for &Vec<u8> {
218 fn encode_type(out: &mut Vec<u8>) {
219 out.push(ColumnType::MYSQL_TYPE_BLOB as u8);
220 out.push(0x00);
221 }
222
223 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
224 write_bytes_lenenc(out, self);
225 Ok(())
226 }
227}
228
229impl<T: TypedParam> TypedParam for Option<T> {
230 fn is_null(&self) -> bool {
231 self.is_none()
232 }
233
234 fn encode_type(out: &mut Vec<u8>) {
235 T::encode_type(out);
236 }
237
238 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
239 match self {
240 Some(value) => value.encode_value(out),
241 None => Ok(()),
242 }
243 }
244}
245
246#[cfg(test)]
251mod tests {
252 use super::*;
253
254 #[test]
255 fn test_param_i32() {
256 let param: i32 = -42;
257 let mut types = Vec::new();
258 let mut values = Vec::new();
259
260 i32::encode_type(&mut types);
261 param.encode_value(&mut values).unwrap();
262
263 assert_eq!(types, vec![ColumnType::MYSQL_TYPE_LONG as u8, 0x00]);
264 assert_eq!(values, (-42i32).to_le_bytes());
265 assert!(!param.is_null());
266 }
267
268 #[test]
269 fn test_param_u64() {
270 let param: u64 = 12345678901234;
271 let mut types = Vec::new();
272 let mut values = Vec::new();
273
274 u64::encode_type(&mut types);
275 param.encode_value(&mut values).unwrap();
276
277 assert_eq!(types, vec![ColumnType::MYSQL_TYPE_LONGLONG as u8, 0x80]);
278 assert_eq!(values, 12345678901234u64.to_le_bytes());
279 }
280
281 #[test]
282 fn test_param_f64() {
283 let param: f64 = 3.14159;
284 let mut types = Vec::new();
285 let mut values = Vec::new();
286
287 f64::encode_type(&mut types);
288 param.encode_value(&mut values).unwrap();
289
290 assert_eq!(types, vec![ColumnType::MYSQL_TYPE_DOUBLE as u8, 0x00]);
291 assert_eq!(values, 3.14159f64.to_bits().to_le_bytes());
292 }
293
294 #[test]
295 fn test_param_str() {
296 let param = "Hello, MySQL!";
297 let mut types = Vec::new();
298 let mut values = Vec::new();
299
300 <&str>::encode_type(&mut types);
301 param.encode_value(&mut values).unwrap();
302
303 assert_eq!(types, vec![ColumnType::MYSQL_TYPE_VAR_STRING as u8, 0x00]);
304 assert_eq!(values[0], 13);
305 assert_eq!(&values[1..], b"Hello, MySQL!");
306 }
307
308 #[test]
309 fn test_param_string() {
310 let param = String::from("Rust");
311 let mut types = Vec::new();
312 let mut values = Vec::new();
313
314 String::encode_type(&mut types);
315 param.encode_value(&mut values).unwrap();
316
317 assert_eq!(types, vec![ColumnType::MYSQL_TYPE_VAR_STRING as u8, 0x00]);
318 assert_eq!(values[0], 4);
319 assert_eq!(&values[1..], b"Rust");
320 }
321
322 #[test]
323 fn test_param_bytes() {
324 let param: &[u8] = &[0xDE, 0xAD, 0xBE, 0xEF];
325 let mut types = Vec::new();
326 let mut values = Vec::new();
327
328 <&[u8]>::encode_type(&mut types);
329 param.encode_value(&mut values).unwrap();
330
331 assert_eq!(types, vec![ColumnType::MYSQL_TYPE_BLOB as u8, 0x00]);
332 assert_eq!(values[0], 4);
333 assert_eq!(&values[1..], &[0xDE, 0xAD, 0xBE, 0xEF]);
334 }
335
336 #[test]
337 fn test_param_vec_u8() {
338 let param = vec![1u8, 2, 3, 4, 5];
339 let mut types = Vec::new();
340 let mut values = Vec::new();
341
342 Vec::<u8>::encode_type(&mut types);
343 param.encode_value(&mut values).unwrap();
344
345 assert_eq!(types, vec![ColumnType::MYSQL_TYPE_BLOB as u8, 0x00]);
346 assert_eq!(values[0], 5);
347 assert_eq!(&values[1..], &[1, 2, 3, 4, 5]);
348 }
349
350 #[test]
351 fn test_param_option_some() {
352 let param = Some(42i32);
353 let mut types = Vec::new();
354 let mut values = Vec::new();
355
356 assert!(!param.is_null());
357 Option::<i32>::encode_type(&mut types);
358 param.encode_value(&mut values).unwrap();
359
360 assert_eq!(types, vec![ColumnType::MYSQL_TYPE_LONG as u8, 0x00]);
361 assert_eq!(values, 42i32.to_le_bytes());
362 }
363
364 #[test]
365 fn test_param_option_none() {
366 let param: Option<i32> = None;
367 let mut types = Vec::new();
368 let mut values = Vec::new();
369
370 assert!(param.is_null());
371 Option::<i32>::encode_type(&mut types);
372 param.encode_value(&mut values).unwrap();
373
374 assert_eq!(types, vec![ColumnType::MYSQL_TYPE_LONG as u8, 0x00]);
375 assert_eq!(values, Vec::<u8>::new());
376 }
377
378 #[test]
379 fn test_param_option_string() {
380 let param = Some("test".to_string());
381 let mut types = Vec::new();
382 let mut values = Vec::new();
383
384 Option::<String>::encode_type(&mut types);
385 param.encode_value(&mut values).unwrap();
386
387 assert_eq!(types, vec![ColumnType::MYSQL_TYPE_VAR_STRING as u8, 0x00]);
388 assert_eq!(values[0], 4);
389 assert_eq!(&values[1..], b"test");
390 }
391}
392
393pub trait Params {
401 fn len(&self) -> usize;
403
404 fn is_empty(&self) -> bool {
405 self.len() == 0
406 }
407
408 fn encode_null_bitmap(&self, out: &mut Vec<u8>);
413
414 fn encode_types(&self, out: &mut Vec<u8>);
420
421 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()>;
426
427 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()>;
435}
436
437#[auto_impl(&)]
438pub trait TypedParams {
439 fn len(&self) -> usize;
440 fn is_empty(&self) -> bool {
441 self.len() == 0
442 }
443 fn encode_null_bitmap(&self, out: &mut Vec<u8>);
444 fn encode_types(out: &mut Vec<u8>);
445 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()>;
446 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()>;
447}
448
449impl<T: TypedParams> Params for T {
450 fn len(&self) -> usize {
451 TypedParams::len(self)
452 }
453 fn encode_null_bitmap(&self, out: &mut Vec<u8>) {
454 TypedParams::encode_null_bitmap(self, out)
455 }
456 fn encode_types(&self, out: &mut Vec<u8>) {
457 T::encode_types(out)
458 }
459 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()> {
460 TypedParams::encode_values(self, out)
461 }
462 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()> {
463 TypedParams::encode_values_for_bulk(self, out)
464 }
465}
466
467impl TypedParams for () {
468 fn len(&self) -> usize {
469 0
470 }
471 fn encode_null_bitmap(&self, _out: &mut Vec<u8>) {}
472 fn encode_types(_out: &mut Vec<u8>) {}
473 fn encode_values(&self, _out: &mut Vec<u8>) -> Result<()> {
474 Ok(())
475 }
476 fn encode_values_for_bulk(&self, _out: &mut Vec<u8>) -> Result<()> {
477 Ok(())
478 }
479}
480
481macro_rules! impl_params_for_tuple {
486 ($($T:ident : $idx:tt),+) => {
487 impl<$($T: TypedParam),+> TypedParams for ($($T,)+) {
488 fn len(&self) -> usize {
489 let mut count = 0;
490 $(
491 let _ = &self.$idx;
492 count += 1;
493 )+
494 count
495 }
496
497 fn encode_null_bitmap(&self, out: &mut Vec<u8>) {
498 let num_bytes = TypedParams::len(self).div_ceil(8);
499 let start_len = out.len();
500 out.resize(start_len + num_bytes, 0);
501
502 $(
503 if self.$idx.is_null() {
504 let byte_pos = start_len + ($idx >> 3);
505 let bit_offset = $idx & 7;
506 out[byte_pos] |= 1 << bit_offset;
507 }
508 )+
509 }
510
511 fn encode_types(out: &mut Vec<u8>) {
512 $(
513 $T::encode_type(out);
514 )+
515 }
516
517 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()> {
518 $(
519 if !self.$idx.is_null() {
520 self.$idx.encode_value(out)?;
521 }
522 )+
523 Ok(())
524 }
525
526 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()> {
527 $(
528 if self.$idx.is_null() {
529 out.push(ParamIndicator::Null as u8);
530 } else {
531 out.push(ParamIndicator::None as u8);
532 self.$idx.encode_value(out)?;
533 }
534 )+
535 Ok(())
536 }
537 }
538 };
539}
540
541impl_params_for_tuple!(T0: 0);
543impl_params_for_tuple!(T0: 0, T1: 1);
544impl_params_for_tuple!(T0: 0, T1: 1, T2: 2);
545impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3);
546impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4);
547impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5);
548impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6);
549impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7);
550impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8);
551impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8, T9: 9);
552impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8, T9: 9, T10: 10);
553impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8, T9: 9, T10: 10, T11: 11);
554
555#[cfg(test)]
560mod params_tests {
561 use super::*;
562
563 #[test]
564 fn test_params_tuple() {
565 let params = (42i32, "hello", 3.14f64);
566 assert_eq!(Params::len(¶ms), 3);
567
568 let mut null_bitmap = Vec::new();
569 Params::encode_null_bitmap(¶ms, &mut null_bitmap);
570 assert_eq!(null_bitmap, vec![0]);
571
572 let mut types = Vec::new();
573 Params::encode_types(¶ms, &mut types);
574 assert_eq!(types.len(), 6);
575
576 let mut values = Vec::new();
577 Params::encode_values(¶ms, &mut values).unwrap();
578 assert!(values.len() > 12);
579 }
580
581 #[test]
582 fn test_params_tuple_with_option() {
583 let params = (Some(42i32), None::<String>, Some("test"));
584 assert_eq!(Params::len(¶ms), 3);
585
586 let mut null_bitmap = Vec::new();
587 Params::encode_null_bitmap(¶ms, &mut null_bitmap);
588 assert_eq!(null_bitmap, vec![0b00000010]);
589
590 let mut values = Vec::new();
591 Params::encode_values(¶ms, &mut values).unwrap();
592 assert_eq!(values.len(), 9);
593 }
594
595 #[test]
596 fn test_params_mixed_types() {
597 let params = (
598 1i8, 2i16, 3i32, 4i64, 5u8, 6u16, 7u32, 8u64, 1.5f32, 2.5f64, "hello",
599 );
600 assert_eq!(Params::len(¶ms), 11);
601
602 let mut types = Vec::new();
603 Params::encode_types(¶ms, &mut types);
604 assert_eq!(types.len(), 22);
605
606 let mut values = Vec::new();
607 Params::encode_values(¶ms, &mut values).unwrap();
608 assert_eq!(values.len(), 48);
609 }
610
611 #[test]
612 fn test_params_string_variants() {
613 let s1 = "hello";
614 let s2 = String::from("world");
615 let s3 = &String::from("test");
616
617 let params = (s1, s2, s3);
618 assert_eq!(Params::len(¶ms), 3);
619
620 let mut values = Vec::new();
621 Params::encode_values(¶ms, &mut values).unwrap();
622 assert_eq!(values.len(), 17);
623 }
624
625 #[test]
626 fn test_params_byte_variants() {
627 let b1: &[u8] = &[1, 2, 3];
628 let b2 = vec![4, 5, 6];
629 let b3 = &vec![7, 8];
630
631 let params = (b1, b2, b3);
632 assert_eq!(Params::len(¶ms), 3);
633
634 let mut out = Vec::new();
635 Params::encode_values(¶ms, &mut out).unwrap();
636 assert_eq!(out.len(), 11);
637 }
638}