1use crate::constant::{ColumnFlags, ColumnType};
7use crate::error::{Error, Result, eyre};
8use crate::protocol::BinaryRowPayload;
9use crate::protocol::command::{ColumnDefinition, ColumnDefinitionTail};
10use crate::protocol::primitive::*;
11use crate::value::{Time8, Time12, Timestamp4, Timestamp7, Timestamp11, Value};
12use simdutf8::basic::from_utf8;
13use zerocopy::FromBytes;
14
15const BINARY_CHARSET: u16 = 63;
17
18pub trait FromRawValue<'buf>: Sized {
23 fn from_null() -> Result<Self> {
24 Err(Error::BadUsageError(format!(
25 "Cannot decode MySQL type NULL to {}",
26 std::any::type_name::<Self>()
27 )))
28 }
29
30 fn from_i8(_v: i8) -> Result<Self> {
31 Err(Error::BadUsageError(format!(
32 "Cannot decode MySQL type TINYINT (i8) to {}",
33 std::any::type_name::<Self>()
34 )))
35 }
36
37 fn from_i16(_v: i16) -> Result<Self> {
38 Err(Error::BadUsageError(format!(
39 "Cannot decode MySQL type SMALLINT (i16) to {}",
40 std::any::type_name::<Self>()
41 )))
42 }
43
44 fn from_i32(_v: i32) -> Result<Self> {
45 Err(Error::BadUsageError(format!(
46 "Cannot decode MySQL type INT (i32) to {}",
47 std::any::type_name::<Self>()
48 )))
49 }
50
51 fn from_i64(_v: i64) -> Result<Self> {
52 Err(Error::BadUsageError(format!(
53 "Cannot decode MySQL type BIGINT (i64) to {}",
54 std::any::type_name::<Self>()
55 )))
56 }
57
58 fn from_u8(_v: u8) -> Result<Self> {
59 Err(Error::BadUsageError(format!(
60 "Cannot decode MySQL type TINYINT UNSIGNED (u8) to {}",
61 std::any::type_name::<Self>()
62 )))
63 }
64
65 fn from_u16(_v: u16) -> Result<Self> {
66 Err(Error::BadUsageError(format!(
67 "Cannot decode MySQL type SMALLINT UNSIGNED (u16) to {}",
68 std::any::type_name::<Self>()
69 )))
70 }
71
72 fn from_u32(_v: u32) -> Result<Self> {
73 Err(Error::BadUsageError(format!(
74 "Cannot decode MySQL type INT UNSIGNED (u32) to {}",
75 std::any::type_name::<Self>()
76 )))
77 }
78
79 fn from_u64(_v: u64) -> Result<Self> {
80 Err(Error::BadUsageError(format!(
81 "Cannot decode MySQL type BIGINT UNSIGNED (u64) to {}",
82 std::any::type_name::<Self>()
83 )))
84 }
85
86 fn from_float(_v: f32) -> Result<Self> {
87 Err(Error::BadUsageError(format!(
88 "Cannot decode MySQL type FLOAT (f32) to {}",
89 std::any::type_name::<Self>()
90 )))
91 }
92
93 fn from_double(_v: f64) -> Result<Self> {
94 Err(Error::BadUsageError(format!(
95 "Cannot decode MySQL type DOUBLE (f64) to {}",
96 std::any::type_name::<Self>()
97 )))
98 }
99
100 fn from_bytes(_v: &'buf [u8]) -> Result<Self> {
101 Err(Error::BadUsageError(format!(
102 "Cannot decode MySQL type BYTES to {}",
103 std::any::type_name::<Self>()
104 )))
105 }
106
107 fn from_str(_v: &'buf [u8]) -> Result<Self> {
108 Err(Error::BadUsageError(format!(
109 "Cannot decode MySQL type STRING to {}",
110 std::any::type_name::<Self>()
111 )))
112 }
113
114 fn from_decimal(_v: &'buf [u8]) -> Result<Self> {
115 Err(Error::BadUsageError(format!(
116 "Cannot decode MySQL type DECIMAL to {}",
117 std::any::type_name::<Self>()
118 )))
119 }
120
121 fn from_date0() -> Result<Self> {
122 Err(Error::BadUsageError(format!(
123 "Cannot decode MySQL type DATE to {}",
124 std::any::type_name::<Self>()
125 )))
126 }
127
128 fn from_date4(_v: &'buf Timestamp4) -> Result<Self> {
129 Err(Error::BadUsageError(format!(
130 "Cannot decode MySQL type DATE to {}",
131 std::any::type_name::<Self>()
132 )))
133 }
134
135 fn from_datetime0() -> Result<Self> {
136 Err(Error::BadUsageError(format!(
137 "Cannot decode MySQL type DATETIME to {}",
138 std::any::type_name::<Self>()
139 )))
140 }
141
142 fn from_datetime4(_v: &'buf Timestamp4) -> Result<Self> {
143 Err(Error::BadUsageError(format!(
144 "Cannot decode MySQL type DATETIME to {}",
145 std::any::type_name::<Self>()
146 )))
147 }
148
149 fn from_datetime7(_v: &'buf Timestamp7) -> Result<Self> {
150 Err(Error::BadUsageError(format!(
151 "Cannot decode MySQL type DATETIME to {}",
152 std::any::type_name::<Self>()
153 )))
154 }
155
156 fn from_datetime11(_v: &'buf Timestamp11) -> Result<Self> {
157 Err(Error::BadUsageError(format!(
158 "Cannot decode MySQL type DATETIME to {}",
159 std::any::type_name::<Self>()
160 )))
161 }
162
163 fn from_time0() -> Result<Self> {
164 Err(Error::BadUsageError(format!(
165 "Cannot decode MySQL type TIME to {}",
166 std::any::type_name::<Self>()
167 )))
168 }
169
170 fn from_time8(_v: &'buf Time8) -> Result<Self> {
171 Err(Error::BadUsageError(format!(
172 "Cannot decode MySQL type TIME to {}",
173 std::any::type_name::<Self>()
174 )))
175 }
176
177 fn from_time12(_v: &'buf Time12) -> Result<Self> {
178 Err(Error::BadUsageError(format!(
179 "Cannot decode MySQL type TIME to {}",
180 std::any::type_name::<Self>()
181 )))
182 }
183}
184
185pub fn parse_value<'buf, T: FromRawValue<'buf>>(
189 col: &ColumnDefinitionTail,
190 is_null: bool,
191 data: &'buf [u8],
192) -> Result<(T, &'buf [u8])> {
193 if is_null {
194 return Ok((T::from_null()?, data));
195 }
196 let is_unsigned = col.flags()?.contains(ColumnFlags::UNSIGNED_FLAG);
197 let is_binary_charset = col.charset() == BINARY_CHARSET;
198
199 match col.column_type()? {
200 ColumnType::MYSQL_TYPE_NULL => Ok((T::from_null()?, data)),
201
202 ColumnType::MYSQL_TYPE_TINY => {
204 let (val, rest) = read_int_1(data)?;
205 let out = if is_unsigned {
206 T::from_u8(val)?
207 } else {
208 T::from_i8(val as i8)?
209 };
210 Ok((out, rest))
211 }
212
213 ColumnType::MYSQL_TYPE_SHORT | ColumnType::MYSQL_TYPE_YEAR => {
214 let (val, rest) = read_int_2(data)?;
215 let out = if is_unsigned {
216 T::from_u16(val)?
217 } else {
218 T::from_i16(val as i16)?
219 };
220 Ok((out, rest))
221 }
222
223 ColumnType::MYSQL_TYPE_INT24 | ColumnType::MYSQL_TYPE_LONG => {
224 let (val, rest) = read_int_4(data)?;
225 let out = if is_unsigned {
226 T::from_u32(val)?
227 } else {
228 T::from_i32(val as i32)?
229 };
230 Ok((out, rest))
231 }
232
233 ColumnType::MYSQL_TYPE_LONGLONG => {
234 let (val, rest) = read_int_8(data)?;
235 let out = if is_unsigned {
236 T::from_u64(val)?
237 } else {
238 T::from_i64(val as i64)?
239 };
240 Ok((out, rest))
241 }
242
243 ColumnType::MYSQL_TYPE_FLOAT => {
245 let (val, rest) = read_int_4(data)?;
246 Ok((T::from_float(f32::from_bits(val))?, rest))
247 }
248
249 ColumnType::MYSQL_TYPE_DOUBLE => {
250 let (val, rest) = read_int_8(data)?;
251 Ok((T::from_double(f64::from_bits(val))?, rest))
252 }
253
254 ColumnType::MYSQL_TYPE_DATE | ColumnType::MYSQL_TYPE_NEWDATE => {
256 let (len, mut rest) = read_int_1(data)?;
257 match len {
258 0 => Ok((T::from_date0()?, rest)),
259 4 => {
260 let ts = Timestamp4::ref_from_bytes(&rest[..4])?;
261 rest = &rest[4..];
262 Ok((T::from_date4(ts)?, rest))
263 }
264 _ => Err(Error::LibraryBug(eyre!("invalid date length: {}", len))),
265 }
266 }
267
268 ColumnType::MYSQL_TYPE_DATETIME
270 | ColumnType::MYSQL_TYPE_TIMESTAMP
271 | ColumnType::MYSQL_TYPE_TIMESTAMP2
272 | ColumnType::MYSQL_TYPE_DATETIME2 => {
273 let (len, mut rest) = read_int_1(data)?;
274 match len {
275 0 => Ok((T::from_datetime0()?, rest)),
276 4 => {
277 let ts = Timestamp4::ref_from_bytes(&rest[..4])?;
278 rest = &rest[4..];
279 Ok((T::from_datetime4(ts)?, rest))
280 }
281 7 => {
282 let ts = Timestamp7::ref_from_bytes(&rest[..7])?;
283 rest = &rest[7..];
284 Ok((T::from_datetime7(ts)?, rest))
285 }
286 11 => {
287 let ts = Timestamp11::ref_from_bytes(&rest[..11])?;
288 rest = &rest[11..];
289 Ok((T::from_datetime11(ts)?, rest))
290 }
291 _ => Err(Error::LibraryBug(eyre!("invalid datetime length: {}", len))),
292 }
293 }
294
295 ColumnType::MYSQL_TYPE_TIME | ColumnType::MYSQL_TYPE_TIME2 => {
297 let (len, mut rest) = read_int_1(data)?;
298 match len {
299 0 => Ok((T::from_time0()?, rest)),
300 8 => {
301 let time = Time8::ref_from_bytes(&rest[..8])?;
302 rest = &rest[8..];
303 Ok((T::from_time8(time)?, rest))
304 }
305 12 => {
306 let time = Time12::ref_from_bytes(&rest[..12])?;
307 rest = &rest[12..];
308 Ok((T::from_time12(time)?, rest))
309 }
310 _ => Err(Error::LibraryBug(eyre!("invalid time length: {}", len))),
311 }
312 }
313
314 ColumnType::MYSQL_TYPE_DECIMAL | ColumnType::MYSQL_TYPE_NEWDECIMAL => {
316 let (bytes, rest) = read_string_lenenc(data)?;
317 Ok((T::from_decimal(bytes)?, rest))
318 }
319
320 ColumnType::MYSQL_TYPE_VARCHAR
322 | ColumnType::MYSQL_TYPE_VAR_STRING
323 | ColumnType::MYSQL_TYPE_STRING
324 | ColumnType::MYSQL_TYPE_BLOB
325 | ColumnType::MYSQL_TYPE_TINY_BLOB
326 | ColumnType::MYSQL_TYPE_MEDIUM_BLOB
327 | ColumnType::MYSQL_TYPE_LONG_BLOB
328 | ColumnType::MYSQL_TYPE_GEOMETRY
329 | ColumnType::MYSQL_TYPE_JSON
330 | ColumnType::MYSQL_TYPE_ENUM
331 | ColumnType::MYSQL_TYPE_SET
332 | ColumnType::MYSQL_TYPE_BIT
333 | ColumnType::MYSQL_TYPE_TYPED_ARRAY => {
334 let (bytes, rest) = read_string_lenenc(data)?;
335 let out = if is_binary_charset {
336 T::from_bytes(bytes)?
337 } else {
338 T::from_str(bytes)?
339 };
340 Ok((out, rest))
341 }
342 }
343}
344
345pub trait FromRawRow<'buf>: Sized {
347 fn from_raw_row(cols: &[ColumnDefinition<'_>], row: BinaryRowPayload<'buf>) -> Result<Self>;
348}
349
350impl<'buf, 'value> FromRawValue<'buf> for Value<'value>
355where
356 'buf: 'value,
357{
358 fn from_null() -> Result<Self> {
359 Ok(Value::Null)
360 }
361
362 fn from_i8(v: i8) -> Result<Self> {
363 Ok(Value::SignedInt(v as i64))
364 }
365
366 fn from_i16(v: i16) -> Result<Self> {
367 Ok(Value::SignedInt(v as i64))
368 }
369
370 fn from_i32(v: i32) -> Result<Self> {
371 Ok(Value::SignedInt(v as i64))
372 }
373
374 fn from_i64(v: i64) -> Result<Self> {
375 Ok(Value::SignedInt(v))
376 }
377
378 fn from_u8(v: u8) -> Result<Self> {
379 Ok(Value::UnsignedInt(v as u64))
380 }
381
382 fn from_u16(v: u16) -> Result<Self> {
383 Ok(Value::UnsignedInt(v as u64))
384 }
385
386 fn from_u32(v: u32) -> Result<Self> {
387 Ok(Value::UnsignedInt(v as u64))
388 }
389
390 fn from_u64(v: u64) -> Result<Self> {
391 Ok(Value::UnsignedInt(v))
392 }
393
394 fn from_float(v: f32) -> Result<Self> {
395 Ok(Value::Float(v))
396 }
397
398 fn from_double(v: f64) -> Result<Self> {
399 Ok(Value::Double(v))
400 }
401
402 fn from_bytes(v: &'buf [u8]) -> Result<Self> {
403 Ok(Value::Byte(v))
404 }
405
406 fn from_str(v: &'buf [u8]) -> Result<Self> {
407 Ok(Value::Byte(v))
408 }
409
410 fn from_decimal(v: &'buf [u8]) -> Result<Self> {
411 Ok(Value::Byte(v))
412 }
413
414 fn from_date0() -> Result<Self> {
415 Ok(Value::Date0)
416 }
417
418 fn from_date4(v: &'buf Timestamp4) -> Result<Self> {
419 Ok(Value::Date4(v))
420 }
421
422 fn from_datetime0() -> Result<Self> {
423 Ok(Value::Datetime0)
424 }
425
426 fn from_datetime4(v: &'buf Timestamp4) -> Result<Self> {
427 Ok(Value::Datetime4(v))
428 }
429
430 fn from_datetime7(v: &'buf Timestamp7) -> Result<Self> {
431 Ok(Value::Datetime7(v))
432 }
433
434 fn from_datetime11(v: &'buf Timestamp11) -> Result<Self> {
435 Ok(Value::Datetime11(v))
436 }
437
438 fn from_time0() -> Result<Self> {
439 Ok(Value::Time0)
440 }
441
442 fn from_time8(v: &'buf Time8) -> Result<Self> {
443 Ok(Value::Time8(v))
444 }
445
446 fn from_time12(v: &'buf Time12) -> Result<Self> {
447 Ok(Value::Time12(v))
448 }
449}
450
451impl FromRawValue<'_> for i8 {
456 fn from_i8(v: i8) -> Result<Self> {
457 Ok(v)
458 }
459}
460
461impl FromRawValue<'_> for i16 {
462 fn from_i8(v: i8) -> Result<Self> {
463 Ok(v as i16)
464 }
465
466 fn from_i16(v: i16) -> Result<Self> {
467 Ok(v)
468 }
469}
470
471impl FromRawValue<'_> for i32 {
472 fn from_i8(v: i8) -> Result<Self> {
473 Ok(v as i32)
474 }
475
476 fn from_i16(v: i16) -> Result<Self> {
477 Ok(v as i32)
478 }
479
480 fn from_i32(v: i32) -> Result<Self> {
481 Ok(v)
482 }
483}
484
485impl FromRawValue<'_> for i64 {
486 fn from_i8(v: i8) -> Result<Self> {
487 Ok(v as i64)
488 }
489
490 fn from_i16(v: i16) -> Result<Self> {
491 Ok(v as i64)
492 }
493
494 fn from_i32(v: i32) -> Result<Self> {
495 Ok(v as i64)
496 }
497
498 fn from_i64(v: i64) -> Result<Self> {
499 Ok(v)
500 }
501}
502
503impl FromRawValue<'_> for bool {
504 fn from_i8(v: i8) -> Result<Self> {
505 Ok(v != 0)
506 }
507
508 fn from_u8(v: u8) -> Result<Self> {
509 Ok(v != 0)
510 }
511}
512
513impl FromRawValue<'_> for u8 {
514 fn from_u8(v: u8) -> Result<Self> {
515 Ok(v)
516 }
517}
518
519impl FromRawValue<'_> for u16 {
520 fn from_u8(v: u8) -> Result<Self> {
521 Ok(v as u16)
522 }
523
524 fn from_u16(v: u16) -> Result<Self> {
525 Ok(v)
526 }
527}
528
529impl FromRawValue<'_> for u32 {
530 fn from_u8(v: u8) -> Result<Self> {
531 Ok(v as u32)
532 }
533
534 fn from_u16(v: u16) -> Result<Self> {
535 Ok(v as u32)
536 }
537
538 fn from_u32(v: u32) -> Result<Self> {
539 Ok(v)
540 }
541}
542
543impl FromRawValue<'_> for u64 {
544 fn from_u8(v: u8) -> Result<Self> {
545 Ok(v as u64)
546 }
547
548 fn from_u16(v: u16) -> Result<Self> {
549 Ok(v as u64)
550 }
551
552 fn from_u32(v: u32) -> Result<Self> {
553 Ok(v as u64)
554 }
555
556 fn from_u64(v: u64) -> Result<Self> {
557 Ok(v)
558 }
559}
560
561impl FromRawValue<'_> for f32 {
562 fn from_float(v: f32) -> Result<Self> {
563 Ok(v)
564 }
565}
566
567impl FromRawValue<'_> for f64 {
568 fn from_double(v: f64) -> Result<Self> {
569 Ok(v)
570 }
571
572 fn from_float(v: f32) -> Result<Self> {
573 Ok(v as f64)
574 }
575}
576
577impl<'a> FromRawValue<'a> for &'a [u8] {
578 fn from_bytes(v: &'a [u8]) -> Result<Self> {
579 Ok(v)
580 }
581}
582
583impl FromRawValue<'_> for Vec<u8> {
584 fn from_bytes(v: &[u8]) -> Result<Self> {
585 Ok(v.to_vec())
586 }
587}
588
589impl<'a> FromRawValue<'a> for &'a str {
590 fn from_str(v: &'a [u8]) -> Result<Self> {
591 from_utf8(v).map_err(|e| {
592 Error::BadUsageError(format!("Cannot decode MySQL type STRING to &str: {}", e))
593 })
594 }
595}
596
597impl FromRawValue<'_> for String {
598 fn from_str(v: &[u8]) -> Result<Self> {
599 from_utf8(v).map(|s| s.to_owned()).map_err(|e| {
600 Error::BadUsageError(format!("Cannot decode MySQL type STRING to String: {}", e))
601 })
602 }
603}
604
605impl<'a, T: FromRawValue<'a>> FromRawValue<'a> for Option<T> {
606 fn from_null() -> Result<Self> {
607 Ok(None)
608 }
609
610 fn from_i8(v: i8) -> Result<Self> {
611 T::from_i8(v).map(Some)
612 }
613
614 fn from_i16(v: i16) -> Result<Self> {
615 T::from_i16(v).map(Some)
616 }
617
618 fn from_i32(v: i32) -> Result<Self> {
619 T::from_i32(v).map(Some)
620 }
621
622 fn from_i64(v: i64) -> Result<Self> {
623 T::from_i64(v).map(Some)
624 }
625
626 fn from_u8(v: u8) -> Result<Self> {
627 T::from_u8(v).map(Some)
628 }
629
630 fn from_u16(v: u16) -> Result<Self> {
631 T::from_u16(v).map(Some)
632 }
633
634 fn from_u32(v: u32) -> Result<Self> {
635 T::from_u32(v).map(Some)
636 }
637
638 fn from_u64(v: u64) -> Result<Self> {
639 T::from_u64(v).map(Some)
640 }
641
642 fn from_float(v: f32) -> Result<Self> {
643 T::from_float(v).map(Some)
644 }
645
646 fn from_double(v: f64) -> Result<Self> {
647 T::from_double(v).map(Some)
648 }
649
650 fn from_bytes(v: &'a [u8]) -> Result<Self> {
651 T::from_bytes(v).map(Some)
652 }
653
654 fn from_str(v: &'a [u8]) -> Result<Self> {
655 T::from_str(v).map(Some)
656 }
657
658 fn from_decimal(v: &'a [u8]) -> Result<Self> {
659 T::from_decimal(v).map(Some)
660 }
661
662 fn from_date0() -> Result<Self> {
663 T::from_date0().map(Some)
664 }
665
666 fn from_date4(v: &'a Timestamp4) -> Result<Self> {
667 T::from_date4(v).map(Some)
668 }
669
670 fn from_datetime0() -> Result<Self> {
671 T::from_datetime0().map(Some)
672 }
673
674 fn from_datetime4(v: &'a Timestamp4) -> Result<Self> {
675 T::from_datetime4(v).map(Some)
676 }
677
678 fn from_datetime7(v: &'a Timestamp7) -> Result<Self> {
679 T::from_datetime7(v).map(Some)
680 }
681
682 fn from_datetime11(v: &'a Timestamp11) -> Result<Self> {
683 T::from_datetime11(v).map(Some)
684 }
685
686 fn from_time0() -> Result<Self> {
687 T::from_time0().map(Some)
688 }
689
690 fn from_time8(v: &'a Time8) -> Result<Self> {
691 T::from_time8(v).map(Some)
692 }
693
694 fn from_time12(v: &'a Time12) -> Result<Self> {
695 T::from_time12(v).map(Some)
696 }
697}
698
699macro_rules! impl_from_raw_row_tuple {
704 ($($idx:tt: $T:ident),+) => {
705 impl<'buf, 'value, $($T: FromRawValue<'buf>),+> FromRawRow<'buf> for ($($T,)+) {
706 #[expect(non_snake_case)]
707 fn from_raw_row(cols: &[ColumnDefinition<'_>], row: BinaryRowPayload<'buf>) -> Result<Self> {
708 let mut data = row.values();
709 let null_bitmap = row.null_bitmap();
710 $(
711 let ($T, rest) = parse_value::<$T>(&cols[$idx].tail, null_bitmap.is_null($idx), data)?;
712 data = rest;
713 )+
714 let _ = data; Ok(($($T,)+))
716 }
717 }
718 };
719}
720
721impl_from_raw_row_tuple!(0: A);
722impl_from_raw_row_tuple!(0: A, 1: B);
723impl_from_raw_row_tuple!(0: A, 1: B, 2: C);
724impl_from_raw_row_tuple!(0: A, 1: B, 2: C, 3: D);
725impl_from_raw_row_tuple!(0: A, 1: B, 2: C, 3: D, 4: E);
726impl_from_raw_row_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F);
727impl_from_raw_row_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G);
728impl_from_raw_row_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H);
729impl_from_raw_row_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I);
730impl_from_raw_row_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J);
731impl_from_raw_row_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K);
732impl_from_raw_row_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K, 11: L);