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 bool {
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, u8::from(*self));
45 Ok(())
46 }
47}
48
49impl TypedParam for i8 {
50 fn encode_type(out: &mut Vec<u8>) {
51 out.push(ColumnType::MYSQL_TYPE_TINY as u8);
52 out.push(0x00);
53 }
54
55 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
56 write_int_1(out, *self as u8);
57 Ok(())
58 }
59}
60
61impl TypedParam for i16 {
62 fn encode_type(out: &mut Vec<u8>) {
63 out.push(ColumnType::MYSQL_TYPE_SHORT as u8);
64 out.push(0x00);
65 }
66
67 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
68 write_int_2(out, *self as u16);
69 Ok(())
70 }
71}
72
73impl TypedParam for i32 {
74 fn encode_type(out: &mut Vec<u8>) {
75 out.push(ColumnType::MYSQL_TYPE_LONG as u8);
76 out.push(0x00);
77 }
78
79 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
80 write_int_4(out, *self as u32);
81 Ok(())
82 }
83}
84
85impl TypedParam for i64 {
86 fn encode_type(out: &mut Vec<u8>) {
87 out.push(ColumnType::MYSQL_TYPE_LONGLONG as u8);
88 out.push(0x00);
89 }
90
91 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
92 write_int_8(out, *self as u64);
93 Ok(())
94 }
95}
96
97impl TypedParam for u8 {
98 fn encode_type(out: &mut Vec<u8>) {
99 out.push(ColumnType::MYSQL_TYPE_TINY as u8);
100 out.push(0x80);
101 }
102
103 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
104 write_int_1(out, *self);
105 Ok(())
106 }
107}
108
109impl TypedParam for u16 {
110 fn encode_type(out: &mut Vec<u8>) {
111 out.push(ColumnType::MYSQL_TYPE_SHORT as u8);
112 out.push(0x80);
113 }
114
115 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
116 write_int_2(out, *self);
117 Ok(())
118 }
119}
120
121impl TypedParam for u32 {
122 fn encode_type(out: &mut Vec<u8>) {
123 out.push(ColumnType::MYSQL_TYPE_LONG as u8);
124 out.push(0x80);
125 }
126
127 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
128 write_int_4(out, *self);
129 Ok(())
130 }
131}
132
133impl TypedParam for u64 {
134 fn encode_type(out: &mut Vec<u8>) {
135 out.push(ColumnType::MYSQL_TYPE_LONGLONG as u8);
136 out.push(0x80);
137 }
138
139 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
140 write_int_8(out, *self);
141 Ok(())
142 }
143}
144
145impl TypedParam for f32 {
146 fn encode_type(out: &mut Vec<u8>) {
147 out.push(ColumnType::MYSQL_TYPE_FLOAT as u8);
148 out.push(0x00);
149 }
150
151 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
152 write_int_4(out, self.to_bits());
153 Ok(())
154 }
155}
156
157impl TypedParam for f64 {
158 fn encode_type(out: &mut Vec<u8>) {
159 out.push(ColumnType::MYSQL_TYPE_DOUBLE as u8);
160 out.push(0x00);
161 }
162
163 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
164 write_int_8(out, self.to_bits());
165 Ok(())
166 }
167}
168
169impl TypedParam for &str {
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 &String {
194 fn encode_type(out: &mut Vec<u8>) {
195 out.push(ColumnType::MYSQL_TYPE_VAR_STRING as u8);
196 out.push(0x00);
197 }
198
199 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
200 write_string_lenenc(out, self);
201 Ok(())
202 }
203}
204
205impl TypedParam for &[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 TypedParam for &Vec<u8> {
230 fn encode_type(out: &mut Vec<u8>) {
231 out.push(ColumnType::MYSQL_TYPE_BLOB as u8);
232 out.push(0x00);
233 }
234
235 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
236 write_bytes_lenenc(out, self);
237 Ok(())
238 }
239}
240
241impl<T: TypedParam> TypedParam for Option<T> {
242 fn is_null(&self) -> bool {
243 self.is_none()
244 }
245
246 fn encode_type(out: &mut Vec<u8>) {
247 T::encode_type(out);
248 }
249
250 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
251 match self {
252 Some(value) => value.encode_value(out),
253 None => Ok(()),
254 }
255 }
256}
257
258pub trait Params {
266 fn len(&self) -> usize;
268
269 fn is_empty(&self) -> bool {
270 self.len() == 0
271 }
272
273 fn encode_null_bitmap(&self, out: &mut Vec<u8>);
278
279 fn encode_types(&self, out: &mut Vec<u8>);
285
286 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()>;
291
292 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()>;
300}
301
302#[auto_impl(&)]
303pub trait TypedParams {
304 fn len(&self) -> usize;
305 fn is_empty(&self) -> bool {
306 self.len() == 0
307 }
308 fn encode_null_bitmap(&self, out: &mut Vec<u8>);
309 fn encode_types(out: &mut Vec<u8>);
310 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()>;
311 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()>;
312}
313
314impl<T: TypedParams> Params for T {
315 fn len(&self) -> usize {
316 TypedParams::len(self)
317 }
318 fn encode_null_bitmap(&self, out: &mut Vec<u8>) {
319 TypedParams::encode_null_bitmap(self, out)
320 }
321 fn encode_types(&self, out: &mut Vec<u8>) {
322 T::encode_types(out)
323 }
324 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()> {
325 TypedParams::encode_values(self, out)
326 }
327 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()> {
328 TypedParams::encode_values_for_bulk(self, out)
329 }
330}
331
332impl TypedParams for () {
333 fn len(&self) -> usize {
334 0
335 }
336 fn encode_null_bitmap(&self, _out: &mut Vec<u8>) {}
337 fn encode_types(_out: &mut Vec<u8>) {}
338 fn encode_values(&self, _out: &mut Vec<u8>) -> Result<()> {
339 Ok(())
340 }
341 fn encode_values_for_bulk(&self, _out: &mut Vec<u8>) -> Result<()> {
342 Ok(())
343 }
344}
345
346macro_rules! impl_params_for_tuple {
351 ($($T:ident : $idx:tt),+) => {
352 impl<$($T: TypedParam),+> TypedParams for ($($T,)+) {
353 fn len(&self) -> usize {
354 let mut count = 0;
355 $(
356 let _ = &self.$idx;
357 count += 1;
358 )+
359 count
360 }
361
362 fn encode_null_bitmap(&self, out: &mut Vec<u8>) {
363 let num_bytes = TypedParams::len(self).div_ceil(8);
364 let start_len = out.len();
365 out.resize(start_len + num_bytes, 0);
366
367 $(
368 if self.$idx.is_null() {
369 let byte_pos = start_len + ($idx >> 3);
370 let bit_offset = $idx & 7;
371 out[byte_pos] |= 1 << bit_offset;
372 }
373 )+
374 }
375
376 fn encode_types(out: &mut Vec<u8>) {
377 $(
378 $T::encode_type(out);
379 )+
380 }
381
382 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()> {
383 $(
384 if !self.$idx.is_null() {
385 self.$idx.encode_value(out)?;
386 }
387 )+
388 Ok(())
389 }
390
391 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()> {
392 $(
393 if self.$idx.is_null() {
394 out.push(ParamIndicator::Null as u8);
395 } else {
396 out.push(ParamIndicator::None as u8);
397 self.$idx.encode_value(out)?;
398 }
399 )+
400 Ok(())
401 }
402 }
403 };
404}
405
406impl_params_for_tuple!(T0: 0);
408impl_params_for_tuple!(T0: 0, T1: 1);
409impl_params_for_tuple!(T0: 0, T1: 1, T2: 2);
410impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3);
411impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4);
412impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5);
413impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6);
414impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7);
415impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8);
416impl_params_for_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8, T9: 9);
417impl_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);
418impl_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);
419
420impl<T: TypedParam> Params for [T] {
425 fn len(&self) -> usize {
426 <[T]>::len(self)
427 }
428
429 fn encode_null_bitmap(&self, out: &mut Vec<u8>) {
430 let num_bytes = self.len().div_ceil(8);
431 let start_len = out.len();
432 out.resize(start_len + num_bytes, 0);
433
434 for (idx, item) in self.iter().enumerate() {
435 if item.is_null() {
436 let byte_pos = start_len + (idx >> 3);
437 let bit_offset = idx & 7;
438 out[byte_pos] |= 1 << bit_offset;
439 }
440 }
441 }
442
443 fn encode_types(&self, out: &mut Vec<u8>) {
444 for _ in self {
445 T::encode_type(out);
446 }
447 }
448
449 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()> {
450 for item in self {
451 if !item.is_null() {
452 item.encode_value(out)?;
453 }
454 }
455 Ok(())
456 }
457
458 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()> {
459 for item in self {
460 if item.is_null() {
461 out.push(ParamIndicator::Null as u8);
462 } else {
463 out.push(ParamIndicator::None as u8);
464 item.encode_value(out)?;
465 }
466 }
467 Ok(())
468 }
469}
470
471impl<T: TypedParam> Params for &[T] {
472 fn len(&self) -> usize {
473 <[T]>::len(self)
474 }
475
476 fn encode_null_bitmap(&self, out: &mut Vec<u8>) {
477 <[T] as Params>::encode_null_bitmap(self, out)
478 }
479
480 fn encode_types(&self, out: &mut Vec<u8>) {
481 <[T] as Params>::encode_types(self, out)
482 }
483
484 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()> {
485 <[T] as Params>::encode_values(self, out)
486 }
487
488 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()> {
489 <[T] as Params>::encode_values_for_bulk(self, out)
490 }
491}
492
493impl<T: TypedParam> Params for Vec<T> {
494 fn len(&self) -> usize {
495 self.as_slice().len()
496 }
497
498 fn encode_null_bitmap(&self, out: &mut Vec<u8>) {
499 self.as_slice().encode_null_bitmap(out)
500 }
501
502 fn encode_types(&self, out: &mut Vec<u8>) {
503 self.as_slice().encode_types(out)
504 }
505
506 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()> {
507 self.as_slice().encode_values(out)
508 }
509
510 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()> {
511 self.as_slice().encode_values_for_bulk(out)
512 }
513}
514
515impl<T: TypedParam> Params for &Vec<T> {
516 fn len(&self) -> usize {
517 self.as_slice().len()
518 }
519
520 fn encode_null_bitmap(&self, out: &mut Vec<u8>) {
521 self.as_slice().encode_null_bitmap(out)
522 }
523
524 fn encode_types(&self, out: &mut Vec<u8>) {
525 self.as_slice().encode_types(out)
526 }
527
528 fn encode_values(&self, out: &mut Vec<u8>) -> Result<()> {
529 self.as_slice().encode_values(out)
530 }
531
532 fn encode_values_for_bulk(&self, out: &mut Vec<u8>) -> Result<()> {
533 self.as_slice().encode_values_for_bulk(out)
534 }
535}
536
537#[cfg(feature = "with-uuid")]
542impl TypedParam for uuid::Uuid {
543 fn encode_type(out: &mut Vec<u8>) {
544 out.push(ColumnType::MYSQL_TYPE_VAR_STRING as u8);
545 out.push(0x00);
546 }
547
548 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
549 let s = self.as_hyphenated().to_string();
550 write_string_lenenc(out, &s);
551 Ok(())
552 }
553}
554
555#[cfg(feature = "with-uuid")]
556impl TypedParam for &uuid::Uuid {
557 fn encode_type(out: &mut Vec<u8>) {
558 out.push(ColumnType::MYSQL_TYPE_VAR_STRING as u8);
559 out.push(0x00);
560 }
561
562 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
563 let s = self.as_hyphenated().to_string();
564 write_string_lenenc(out, &s);
565 Ok(())
566 }
567}
568
569#[cfg(feature = "with-chrono")]
574use chrono::{Datelike, Timelike};
575
576#[cfg(feature = "with-chrono")]
577impl TypedParam for chrono::NaiveDate {
578 fn encode_type(out: &mut Vec<u8>) {
579 out.push(ColumnType::MYSQL_TYPE_DATE as u8);
580 out.push(0x00);
581 }
582
583 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
584 out.push(4); write_int_2(out, u16::try_from(self.year()).unwrap_or(0));
586 out.push(self.month() as u8);
587 out.push(self.day() as u8);
588 Ok(())
589 }
590}
591
592#[cfg(feature = "with-chrono")]
593impl TypedParam for chrono::NaiveTime {
594 fn encode_type(out: &mut Vec<u8>) {
595 out.push(ColumnType::MYSQL_TYPE_TIME as u8);
596 out.push(0x00);
597 }
598
599 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
600 let micros = self.nanosecond() / 1000;
601 if micros > 0 {
602 out.push(12); out.push(0); write_int_4(out, 0); out.push(self.hour() as u8);
606 out.push(self.minute() as u8);
607 out.push(self.second() as u8);
608 write_int_4(out, micros);
609 } else {
610 out.push(8); out.push(0); write_int_4(out, 0); out.push(self.hour() as u8);
614 out.push(self.minute() as u8);
615 out.push(self.second() as u8);
616 }
617 Ok(())
618 }
619}
620
621#[cfg(feature = "with-chrono")]
622impl TypedParam for chrono::NaiveDateTime {
623 fn encode_type(out: &mut Vec<u8>) {
624 out.push(ColumnType::MYSQL_TYPE_DATETIME as u8);
625 out.push(0x00);
626 }
627
628 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
629 let micros = self.and_utc().timestamp_subsec_micros();
630 if micros > 0 {
631 out.push(11); write_int_2(out, u16::try_from(self.year()).unwrap_or(0));
633 out.push(self.month() as u8);
634 out.push(self.day() as u8);
635 out.push(self.hour() as u8);
636 out.push(self.minute() as u8);
637 out.push(self.second() as u8);
638 write_int_4(out, micros);
639 } else {
640 out.push(7); write_int_2(out, u16::try_from(self.year()).unwrap_or(0));
642 out.push(self.month() as u8);
643 out.push(self.day() as u8);
644 out.push(self.hour() as u8);
645 out.push(self.minute() as u8);
646 out.push(self.second() as u8);
647 }
648 Ok(())
649 }
650}
651
652#[cfg(feature = "with-time")]
657impl TypedParam for time::Date {
658 fn encode_type(out: &mut Vec<u8>) {
659 out.push(ColumnType::MYSQL_TYPE_DATE as u8);
660 out.push(0x00);
661 }
662
663 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
664 out.push(4); write_int_2(out, u16::try_from(self.year()).unwrap_or(0));
666 out.push(self.month() as u8);
667 out.push(self.day());
668 Ok(())
669 }
670}
671
672#[cfg(feature = "with-time")]
673impl TypedParam for time::Time {
674 fn encode_type(out: &mut Vec<u8>) {
675 out.push(ColumnType::MYSQL_TYPE_TIME as u8);
676 out.push(0x00);
677 }
678
679 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
680 let micros = self.microsecond();
681 if micros > 0 {
682 out.push(12); out.push(0); write_int_4(out, 0); out.push(self.hour());
686 out.push(self.minute());
687 out.push(self.second());
688 write_int_4(out, micros);
689 } else {
690 out.push(8); out.push(0); write_int_4(out, 0); out.push(self.hour());
694 out.push(self.minute());
695 out.push(self.second());
696 }
697 Ok(())
698 }
699}
700
701#[cfg(feature = "with-time")]
702impl TypedParam for time::PrimitiveDateTime {
703 fn encode_type(out: &mut Vec<u8>) {
704 out.push(ColumnType::MYSQL_TYPE_DATETIME as u8);
705 out.push(0x00);
706 }
707
708 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
709 let micros = self.microsecond();
710 if micros > 0 {
711 out.push(11); write_int_2(out, u16::try_from(self.year()).unwrap_or(0));
713 out.push(self.month() as u8);
714 out.push(self.day());
715 out.push(self.hour());
716 out.push(self.minute());
717 out.push(self.second());
718 write_int_4(out, micros);
719 } else {
720 out.push(7); write_int_2(out, u16::try_from(self.year()).unwrap_or(0));
722 out.push(self.month() as u8);
723 out.push(self.day());
724 out.push(self.hour());
725 out.push(self.minute());
726 out.push(self.second());
727 }
728 Ok(())
729 }
730}
731
732#[cfg(feature = "with-rust-decimal")]
737impl TypedParam for rust_decimal::Decimal {
738 fn encode_type(out: &mut Vec<u8>) {
739 out.push(ColumnType::MYSQL_TYPE_NEWDECIMAL as u8);
740 out.push(0x00);
741 }
742
743 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
744 let s = self.to_string();
745 write_string_lenenc(out, &s);
746 Ok(())
747 }
748}
749
750#[cfg(feature = "with-rust-decimal")]
751impl TypedParam for &rust_decimal::Decimal {
752 fn encode_type(out: &mut Vec<u8>) {
753 out.push(ColumnType::MYSQL_TYPE_NEWDECIMAL as u8);
754 out.push(0x00);
755 }
756
757 fn encode_value(&self, out: &mut Vec<u8>) -> Result<()> {
758 let s = self.to_string();
759 write_string_lenenc(out, &s);
760 Ok(())
761 }
762}