1use btoi::{btoi, btou};
10use num_traits::ToPrimitive;
11use regex::bytes::Regex;
12
13use std::{
14 any::type_name,
15 borrow::Cow,
16 convert::{TryFrom, TryInto},
17 rc::Rc,
18 str::from_utf8,
19 sync::{Arc, LazyLock},
20 time::Duration,
21};
22
23use crate::value::Value;
24
25pub mod bigdecimal;
26pub mod bigint;
27pub mod chrono;
28pub mod decimal;
29pub mod time;
30pub mod uuid;
31
32#[cfg(feature = "chrono")]
33static DATETIME_RE_YMD: LazyLock<Regex> =
34 LazyLock::new(|| Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap());
35#[cfg(feature = "chrono")]
36static DATETIME_RE_YMD_HMS: LazyLock<Regex> =
37 LazyLock::new(|| Regex::new(r"^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$").unwrap());
38#[cfg(feature = "chrono")]
39static DATETIME_RE_YMD_HMS_NS: LazyLock<Regex> =
40 LazyLock::new(|| Regex::new(r"^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{1,6}$").unwrap());
41static TIME_RE_HH_MM_SS: LazyLock<Regex> =
42 LazyLock::new(|| Regex::new(r"^\d{2}:[0-5]\d:[0-5]\d$").unwrap());
43static TIME_RE_HH_MM_SS_MS: LazyLock<Regex> =
44 LazyLock::new(|| Regex::new(r"^\d{2}:[0-5]\d:[0-5]\d\.\d{1,6}$").unwrap());
45static TIME_RE_HHH_MM_SS: LazyLock<Regex> =
46 LazyLock::new(|| Regex::new(r"^[0-8]\d\d:[0-5]\d:[0-5]\d$").unwrap());
47static TIME_RE_HHH_MM_SS_MS: LazyLock<Regex> =
48 LazyLock::new(|| Regex::new(r"^[0-8]\d\d:[0-5]\d:[0-5]\d\.\d{1,6}$").unwrap());
49
50#[cfg(feature = "chrono")]
52fn parse_mysql_datetime_string(bytes: &[u8]) -> Option<(u32, u32, u32, u32, u32, u32, u32)> {
53 let len = bytes.len();
54
55 #[derive(PartialEq, Eq, PartialOrd, Ord)]
56 #[repr(u8)]
57 enum DateTimeKind {
58 Ymd = 0,
59 YmdHms,
60 YmdHmsMs,
61 }
62
63 let kind = if len == 10 && DATETIME_RE_YMD.is_match(bytes) {
64 DateTimeKind::Ymd
65 } else if len == 19 && DATETIME_RE_YMD_HMS.is_match(bytes) {
66 DateTimeKind::YmdHms
67 } else if 20 < len && len < 27 && DATETIME_RE_YMD_HMS_NS.is_match(bytes) {
68 DateTimeKind::YmdHmsMs
69 } else {
70 return None;
71 };
72
73 let (year, month, day, hour, minute, second, micros) = match kind {
74 DateTimeKind::Ymd => (..4, 5..7, 8..10, None, None, None, None),
75 DateTimeKind::YmdHms => (
76 ..4,
77 5..7,
78 8..10,
79 Some(11..13),
80 Some(14..16),
81 Some(17..19),
82 None,
83 ),
84 DateTimeKind::YmdHmsMs => (
85 ..4,
86 5..7,
87 8..10,
88 Some(11..13),
89 Some(14..16),
90 Some(17..19),
91 Some(20..),
92 ),
93 };
94
95 Some((
96 btou(&bytes[year]).unwrap(),
97 btou(&bytes[month]).unwrap(),
98 btou(&bytes[day]).unwrap(),
99 hour.map(|pos| btou(&bytes[pos]).unwrap()).unwrap_or(0),
100 minute.map(|pos| btou(&bytes[pos]).unwrap()).unwrap_or(0),
101 second.map(|pos| btou(&bytes[pos]).unwrap()).unwrap_or(0),
102 micros.map(|pos| parse_micros(&bytes[pos])).unwrap_or(0),
103 ))
104}
105
106#[derive(Debug, Clone, PartialEq, thiserror::Error)]
108#[error("Couldn't convert the value `{:?}` to a desired type", _0)]
109pub struct FromValueError(pub Value);
110
111pub trait FromValue: Sized {
117 type Intermediate: TryFrom<Value, Error = FromValueError> + Into<Self>;
118
119 fn from_value(v: Value) -> Self {
121 match Self::from_value_opt(v) {
122 Ok(this) => this,
123 Err(e) => panic!("Could not retrieve `{}`: {e}", type_name::<Self>(),),
124 }
125 }
126
127 fn from_value_opt(v: Value) -> Result<Self, FromValueError> {
129 Self::Intermediate::try_from(v).map(Into::into)
130 }
131
132 fn get_intermediate(v: Value) -> Result<Self::Intermediate, FromValueError> {
134 Self::Intermediate::try_from(v)
135 }
136}
137
138#[derive(Debug, Clone, PartialEq)]
140pub struct ParseIr<T>(pub T, pub Value);
141
142impl<T> ParseIr<T> {
143 pub fn commit(self) -> T {
144 self.0
145 }
146
147 pub fn rollback(self) -> Value {
148 self.1
149 }
150}
151
152#[derive(Debug, Clone, PartialEq)]
154pub enum ParseIrOpt<T> {
155 Ready(T),
157 Parsed(T, Value),
159}
160
161impl<T> ParseIrOpt<T> {
162 pub fn commit(self) -> T {
163 match self {
164 ParseIrOpt::Ready(t) | ParseIrOpt::Parsed(t, _) => t,
165 }
166 }
167
168 pub fn rollback(self) -> Value
169 where
170 T: Into<Value>,
171 {
172 match self {
173 ParseIrOpt::Ready(t) => t.into(),
174 ParseIrOpt::Parsed(_, v) => v,
175 }
176 }
177}
178
179macro_rules! impl_from_value_num {
180 ($ty:ident) => {
181 impl TryFrom<Value> for ParseIrOpt<$ty> {
182 type Error = FromValueError;
183
184 fn try_from(v: Value) -> Result<Self, Self::Error> {
185 match v {
186 Value::Int(x) => $ty::try_from(x)
187 .map(ParseIrOpt::Ready)
188 .map_err(|_| FromValueError(Value::Int(x))),
189 Value::UInt(x) => $ty::try_from(x)
190 .map(ParseIrOpt::Ready)
191 .map_err(|_| FromValueError(Value::UInt(x))),
192 Value::Bytes(bytes) => match btoi(&*bytes) {
193 Ok(x) => Ok(ParseIrOpt::Parsed(x, Value::Bytes(bytes))),
194 _ => Err(FromValueError(Value::Bytes(bytes))),
195 },
196 v => Err(FromValueError(v)),
197 }
198 }
199 }
200
201 impl From<ParseIrOpt<$ty>> for $ty {
202 fn from(value: ParseIrOpt<$ty>) -> Self {
203 value.commit()
204 }
205 }
206
207 impl From<ParseIrOpt<$ty>> for Value {
208 fn from(value: ParseIrOpt<$ty>) -> Self {
209 value.rollback()
210 }
211 }
212
213 impl FromValue for $ty {
214 type Intermediate = ParseIrOpt<$ty>;
215 }
216 };
217}
218
219impl_from_value_num!(i8);
220impl_from_value_num!(u8);
221impl_from_value_num!(i16);
222impl_from_value_num!(u16);
223impl_from_value_num!(i32);
224impl_from_value_num!(u32);
225impl_from_value_num!(i64);
226impl_from_value_num!(u64);
227impl_from_value_num!(isize);
228impl_from_value_num!(usize);
229impl_from_value_num!(i128);
230impl_from_value_num!(u128);
231
232impl TryFrom<Value> for ParseIrOpt<bool> {
233 type Error = FromValueError;
234
235 fn try_from(v: Value) -> Result<Self, Self::Error> {
236 match v {
237 Value::Int(0) | Value::UInt(0) => Ok(ParseIrOpt::Ready(false)),
238 Value::Int(_) | Value::UInt(_) => Ok(ParseIrOpt::Ready(true)),
239 Value::Bytes(ref bytes) => match bytes.as_slice() {
240 [b'0'] => Ok(ParseIrOpt::Parsed(false, v)),
241 [b'1'] => Ok(ParseIrOpt::Parsed(true, v)),
242 _ => Err(FromValueError(v)),
243 },
244 v => Err(FromValueError(v)),
245 }
246 }
247}
248
249impl From<ParseIrOpt<bool>> for bool {
250 fn from(value: ParseIrOpt<bool>) -> Self {
251 value.commit()
252 }
253}
254
255impl From<ParseIrOpt<bool>> for Value {
256 fn from(value: ParseIrOpt<bool>) -> Self {
257 value.rollback()
258 }
259}
260
261impl FromValue for bool {
262 type Intermediate = ParseIrOpt<bool>;
263}
264
265impl TryFrom<Value> for ParseIrOpt<f32> {
266 type Error = FromValueError;
267
268 fn try_from(v: Value) -> Result<Self, Self::Error> {
269 match v {
270 Value::Float(x) => Ok(ParseIrOpt::Ready(x)),
271 Value::Bytes(bytes) => match from_utf8(&bytes) {
272 Ok(f) => match f.parse::<f32>() {
273 Ok(x) => Ok(ParseIrOpt::Parsed(x, Value::Bytes(bytes))),
274 _ => Err(FromValueError(Value::Bytes(bytes))),
275 },
276 _ => Err(FromValueError(Value::Bytes(bytes))),
277 },
278 v => Err(FromValueError(v)),
279 }
280 }
281}
282
283impl From<ParseIrOpt<f32>> for f32 {
284 fn from(value: ParseIrOpt<f32>) -> Self {
285 value.commit()
286 }
287}
288
289impl From<ParseIrOpt<f32>> for Value {
290 fn from(value: ParseIrOpt<f32>) -> Self {
291 value.rollback()
292 }
293}
294
295impl FromValue for f32 {
296 type Intermediate = ParseIrOpt<f32>;
297}
298
299impl TryFrom<Value> for ParseIrOpt<f64> {
300 type Error = FromValueError;
301
302 fn try_from(v: Value) -> Result<Self, Self::Error> {
303 match v {
304 Value::Double(x) => Ok(ParseIrOpt::Ready(x)),
305 Value::Float(x) => Ok(ParseIrOpt::Ready(x.into())),
306 Value::Bytes(bytes) => match from_utf8(&bytes) {
307 Ok(f) => match f.parse::<f64>() {
308 Ok(x) => Ok(ParseIrOpt::Parsed(x, Value::Bytes(bytes))),
309 _ => Err(FromValueError(Value::Bytes(bytes))),
310 },
311 _ => Err(FromValueError(Value::Bytes(bytes))),
312 },
313 v => Err(FromValueError(v)),
314 }
315 }
316}
317
318impl From<ParseIrOpt<f64>> for f64 {
319 fn from(value: ParseIrOpt<f64>) -> Self {
320 value.commit()
321 }
322}
323
324impl From<ParseIrOpt<f64>> for Value {
325 fn from(value: ParseIrOpt<f64>) -> Self {
326 value.rollback()
327 }
328}
329
330impl FromValue for f64 {
331 type Intermediate = ParseIrOpt<f64>;
332}
333
334fn mysql_time_to_duration(
335 days: u32,
336 hours: u8,
337 minutes: u8,
338 seconds: u8,
339 microseconds: u32,
340) -> Duration {
341 let nanos = (microseconds) * 1000;
342 let secs = u64::from(seconds)
343 + u64::from(minutes) * 60
344 + u64::from(hours) * 60 * 60
345 + u64::from(days) * 60 * 60 * 24;
346 Duration::new(secs, nanos)
347}
348
349impl TryFrom<Value> for ParseIrOpt<Duration> {
350 type Error = FromValueError;
351
352 fn try_from(v: Value) -> Result<Self, Self::Error> {
353 match v {
354 Value::Time(false, days, hours, minutes, seconds, microseconds) => {
355 let duration = mysql_time_to_duration(days, hours, minutes, seconds, microseconds);
356 Ok(ParseIrOpt::Parsed(duration, v))
357 }
358 Value::Bytes(ref val_bytes) => {
359 let duration = match parse_mysql_time_string(val_bytes) {
360 Some((false, hours, minutes, seconds, microseconds)) => {
361 let days = hours / 24;
362 let hours = (hours % 24) as u8;
363 mysql_time_to_duration(days, hours, minutes, seconds, microseconds)
364 }
365 _ => return Err(FromValueError(v)),
366 };
367 Ok(ParseIrOpt::Parsed(duration, v))
368 }
369 v => Err(FromValueError(v)),
370 }
371 }
372}
373
374impl From<ParseIrOpt<Duration>> for Duration {
375 fn from(value: ParseIrOpt<Duration>) -> Self {
376 value.commit()
377 }
378}
379
380impl From<ParseIrOpt<Duration>> for Value {
381 fn from(value: ParseIrOpt<Duration>) -> Self {
382 value.rollback()
383 }
384}
385
386impl FromValue for Duration {
387 type Intermediate = ParseIrOpt<Duration>;
388}
389
390impl TryFrom<Value> for String {
391 type Error = FromValueError;
392
393 fn try_from(v: Value) -> Result<Self, Self::Error> {
394 match v {
395 Value::Bytes(bytes) => match String::from_utf8(bytes) {
396 Ok(x) => Ok(x),
397 Err(e) => Err(FromValueError(Value::Bytes(e.into_bytes()))),
398 },
399 v => Err(FromValueError(v)),
400 }
401 }
402}
403
404impl FromValue for String {
405 type Intermediate = String;
406}
407
408impl TryFrom<Value> for Vec<u8> {
409 type Error = FromValueError;
410
411 fn try_from(v: Value) -> Result<Self, Self::Error> {
412 match v {
413 Value::Bytes(bytes) => Ok(bytes),
414 v => Err(FromValueError(v)),
415 }
416 }
417}
418
419impl FromValue for Vec<u8> {
420 type Intermediate = Vec<u8>;
421}
422
423impl TryFrom<Value> for Arc<[u8]> {
424 type Error = FromValueError;
425
426 fn try_from(v: Value) -> Result<Self, Self::Error> {
427 match v {
428 Value::Bytes(bytes) => Ok(bytes.into()),
429 v => Err(FromValueError(v)),
430 }
431 }
432}
433
434impl FromValue for Arc<[u8]> {
435 type Intermediate = Arc<[u8]>;
436}
437
438impl TryFrom<Value> for Rc<[u8]> {
439 type Error = FromValueError;
440
441 fn try_from(v: Value) -> Result<Self, Self::Error> {
442 match v {
443 Value::Bytes(bytes) => Ok(bytes.into()),
444 v => Err(FromValueError(v)),
445 }
446 }
447}
448
449impl FromValue for Rc<[u8]> {
450 type Intermediate = Rc<[u8]>;
451}
452
453impl TryFrom<Value> for Box<[u8]> {
454 type Error = FromValueError;
455
456 fn try_from(v: Value) -> Result<Self, Self::Error> {
457 match v {
458 Value::Bytes(bytes) => Ok(bytes.into()),
459 v => Err(FromValueError(v)),
460 }
461 }
462}
463
464impl FromValue for Box<[u8]> {
465 type Intermediate = Box<[u8]>;
466}
467
468impl TryFrom<Value> for Arc<str> {
469 type Error = FromValueError;
470
471 fn try_from(v: Value) -> Result<Self, Self::Error> {
472 match v {
473 Value::Bytes(bytes) => match String::from_utf8(bytes) {
474 Ok(x) => Ok(x.into()),
475 Err(e) => Err(FromValueError(Value::Bytes(e.into_bytes()))),
476 },
477 v => Err(FromValueError(v)),
478 }
479 }
480}
481
482impl FromValue for Arc<str> {
483 type Intermediate = Arc<str>;
484}
485
486impl TryFrom<Value> for Rc<str> {
487 type Error = FromValueError;
488
489 fn try_from(v: Value) -> Result<Self, Self::Error> {
490 match v {
491 Value::Bytes(bytes) => match String::from_utf8(bytes) {
492 Ok(x) => Ok(x.into()),
493 Err(e) => Err(FromValueError(Value::Bytes(e.into_bytes()))),
494 },
495 v => Err(FromValueError(v)),
496 }
497 }
498}
499
500impl FromValue for Rc<str> {
501 type Intermediate = Rc<str>;
502}
503
504impl TryFrom<Value> for Box<str> {
505 type Error = FromValueError;
506
507 fn try_from(v: Value) -> Result<Self, Self::Error> {
508 match v {
509 Value::Bytes(bytes) => match String::from_utf8(bytes) {
510 Ok(x) => Ok(x.into()),
511 Err(e) => Err(FromValueError(Value::Bytes(e.into_bytes()))),
512 },
513 v => Err(FromValueError(v)),
514 }
515 }
516}
517
518impl FromValue for Box<str> {
519 type Intermediate = Box<str>;
520}
521
522#[derive(Debug, Clone, PartialEq)]
524pub enum OptionIr2<T: FromValue> {
525 None,
526 Some(T::Intermediate),
527}
528
529impl<T: FromValue> TryFrom<Value> for OptionIr2<T> {
530 type Error = <<T as FromValue>::Intermediate as TryFrom<Value>>::Error;
531
532 fn try_from(value: Value) -> Result<Self, Self::Error> {
533 match value {
534 Value::NULL => Ok(Self::None),
535 v => <T as FromValue>::Intermediate::try_from(v).map(Self::Some),
536 }
537 }
538}
539
540impl<T: FromValue> From<OptionIr2<T>> for Option<T> {
541 fn from(ir: OptionIr2<T>) -> Self {
542 match ir {
543 OptionIr2::None => None,
544 OptionIr2::Some(ir) => Some(ir.into()),
545 }
546 }
547}
548
549impl<T: FromValue> From<OptionIr2<T>> for Value
550where
551 <T as FromValue>::Intermediate: Into<Value>,
552{
553 fn from(ir: OptionIr2<T>) -> Self {
554 match ir {
555 OptionIr2::None => Value::NULL,
556 OptionIr2::Some(ir) => ir.into(),
557 }
558 }
559}
560
561impl<T: FromValue> FromValue for Option<T> {
562 type Intermediate = OptionIr2<T>;
563}
564
565#[derive(Debug, Clone, PartialEq, PartialOrd)]
567#[repr(transparent)]
568pub struct ValueIr(pub Value);
569
570impl TryFrom<Value> for ValueIr {
571 type Error = FromValueError;
572
573 fn try_from(value: Value) -> Result<Self, Self::Error> {
574 Ok(ValueIr(value))
575 }
576}
577
578impl From<ValueIr> for Value {
579 fn from(value: ValueIr) -> Self {
580 value.0
581 }
582}
583
584impl FromValue for Value {
585 type Intermediate = ValueIr;
586}
587
588pub fn from_value<T: FromValue>(v: Value) -> T {
590 FromValue::from_value(v)
591}
592
593pub fn from_value_opt<T: FromValue>(v: Value) -> Result<T, FromValueError> {
595 FromValue::from_value_opt(v)
596}
597
598impl TryFrom<Value> for Cow<'static, str> {
599 type Error = FromValueError;
600
601 fn try_from(v: Value) -> Result<Self, Self::Error> {
602 match v {
603 Value::Bytes(bytes) => match String::from_utf8(bytes) {
604 Ok(x) => Ok(Cow::Owned(x)),
605 Err(e) => Err(FromValueError(Value::Bytes(e.into_bytes()))),
606 },
607 v => Err(FromValueError(v)),
608 }
609 }
610}
611
612impl FromValue for Cow<'static, str> {
613 type Intermediate = String;
614}
615
616impl TryFrom<Value> for Cow<'static, [u8]> {
617 type Error = FromValueError;
618
619 fn try_from(v: Value) -> Result<Self, Self::Error> {
620 match v {
621 Value::Bytes(x) => Ok(Cow::Owned(x)),
622 v => Err(FromValueError(v)),
623 }
624 }
625}
626
627impl FromValue for Cow<'static, [u8]> {
628 type Intermediate = Cow<'static, [u8]>;
629}
630
631impl<const N: usize> TryFrom<Value> for [u8; N] {
632 type Error = FromValueError;
633
634 fn try_from(v: Value) -> Result<Self, Self::Error> {
635 match v {
636 Value::Bytes(bytes) => bytes
637 .try_into()
638 .map_err(|x| FromValueError(Value::Bytes(x))),
639 v => Err(FromValueError(v)),
640 }
641 }
642}
643
644impl<const N: usize> FromValue for [u8; N] {
645 type Intermediate = [u8; N];
646}
647
648fn parse_micros(micros_bytes: &[u8]) -> u32 {
649 let mut micros = btou(micros_bytes).unwrap();
650
651 let mut pad_zero_cnt = 0;
652 for b in micros_bytes.iter() {
653 if *b == b'0' {
654 pad_zero_cnt += 1;
655 } else {
656 break;
657 }
658 }
659
660 for _ in 0..(6 - pad_zero_cnt - (micros_bytes.len() - pad_zero_cnt)) {
661 micros *= 10;
662 }
663 micros
664}
665
666fn parse_mysql_time_string(mut bytes: &[u8]) -> Option<(bool, u32, u8, u8, u32)> {
668 #[derive(PartialEq, Eq, PartialOrd, Ord)]
669 #[repr(u8)]
670 enum TimeKind {
671 HhMmSs = 0,
672 HhhMmSs,
673 HhMmSsMs,
674 HhhMmSsMs,
675 }
676
677 if bytes.len() < 8 {
678 return None;
679 }
680
681 let is_neg = bytes[0] == b'-';
682 if is_neg {
683 bytes = &bytes[1..];
684 }
685
686 let len = bytes.len();
687
688 let kind = if len == 8 && TIME_RE_HH_MM_SS.is_match(bytes) {
689 TimeKind::HhMmSs
690 } else if len == 9 && TIME_RE_HHH_MM_SS.is_match(bytes) {
691 TimeKind::HhhMmSs
692 } else if TIME_RE_HH_MM_SS_MS.is_match(bytes) {
693 TimeKind::HhMmSsMs
694 } else if TIME_RE_HHH_MM_SS_MS.is_match(bytes) {
695 TimeKind::HhhMmSsMs
696 } else {
697 return None;
698 };
699
700 let (hour_pos, min_pos, sec_pos, micros_pos) = match kind {
701 TimeKind::HhMmSs => (..2, 3..5, 6..8, None),
702 TimeKind::HhMmSsMs => (..2, 3..5, 6..8, Some(9..)),
703 TimeKind::HhhMmSs => (..3, 4..6, 7..9, None),
704 TimeKind::HhhMmSsMs => (..3, 4..6, 7..9, Some(10..)),
705 };
706
707 Some((
708 is_neg,
709 btou(&bytes[hour_pos]).unwrap(),
710 btou(&bytes[min_pos]).unwrap(),
711 btou(&bytes[sec_pos]).unwrap(),
712 micros_pos.map(|pos| parse_micros(&bytes[pos])).unwrap_or(0),
713 ))
714}
715
716impl From<Duration> for Value {
717 fn from(x: Duration) -> Value {
718 let mut secs_total = x.as_secs();
719 let micros = (f64::from(x.subsec_nanos()) / 1000_f64).round() as u32;
720 let seconds = (secs_total % 60) as u8;
721 secs_total -= u64::from(seconds);
722 let minutes = ((secs_total % (60 * 60)) / 60) as u8;
723 secs_total -= u64::from(minutes) * 60;
724 let hours = ((secs_total % (60 * 60 * 24)) / (60 * 60)) as u8;
725 secs_total -= u64::from(hours) * 60 * 60;
726 Value::Time(
727 false,
728 (secs_total / (60 * 60 * 24)) as u32,
729 hours,
730 minutes,
731 seconds,
732 micros,
733 )
734 }
735}
736
737pub trait ToValue {
738 fn to_value(&self) -> Value;
739}
740
741impl<T: Into<Value> + Clone> ToValue for T {
742 fn to_value(&self) -> Value {
743 self.clone().into()
744 }
745}
746
747impl<'a, T: ToValue> From<&'a T> for Value {
748 fn from(x: &'a T) -> Value {
749 x.to_value()
750 }
751}
752
753impl<T: Into<Value>> From<Option<T>> for Value {
754 fn from(x: Option<T>) -> Value {
755 match x {
756 None => Value::NULL,
757 Some(x) => x.into(),
758 }
759 }
760}
761
762macro_rules! into_value_impl (
763 (signed $t:ty) => (
764 impl From<$t> for Value {
765 fn from(x: $t) -> Value {
766 Value::Int(x as i64)
767 }
768 }
769 );
770 (unsigned $t:ty) => (
771 impl From<$t> for Value {
772 fn from(x: $t) -> Value {
773 Value::UInt(x as u64)
774 }
775 }
776 );
777);
778
779into_value_impl!(signed i8);
780into_value_impl!(signed i16);
781into_value_impl!(signed i32);
782into_value_impl!(signed i64);
783into_value_impl!(signed isize);
784into_value_impl!(unsigned u8);
785into_value_impl!(unsigned u16);
786into_value_impl!(unsigned u32);
787into_value_impl!(unsigned u64);
788into_value_impl!(unsigned usize);
789
790impl From<i128> for Value {
791 fn from(x: i128) -> Value {
792 if let Some(x) = x.to_i64() {
793 Value::Int(x)
794 } else if let Some(x) = x.to_u64() {
795 Value::UInt(x)
796 } else {
797 Value::Bytes(x.to_string().into())
798 }
799 }
800}
801
802impl From<u128> for Value {
803 fn from(x: u128) -> Value {
804 if let Some(x) = x.to_u64() {
805 Value::UInt(x)
806 } else {
807 Value::Bytes(x.to_string().into())
808 }
809 }
810}
811
812impl From<f32> for Value {
813 fn from(x: f32) -> Value {
814 Value::Float(x)
815 }
816}
817
818impl From<f64> for Value {
819 fn from(x: f64) -> Value {
820 Value::Double(x)
821 }
822}
823
824impl From<bool> for Value {
825 fn from(x: bool) -> Value {
826 Value::Int(if x { 1 } else { 0 })
827 }
828}
829
830impl<'a> From<&'a [u8]> for Value {
831 fn from(x: &'a [u8]) -> Value {
832 Value::Bytes(x.into())
833 }
834}
835
836impl From<Box<[u8]>> for Value {
837 fn from(x: Box<[u8]>) -> Value {
838 Value::Bytes(x.into())
839 }
840}
841
842impl From<Arc<[u8]>> for Value {
843 fn from(x: Arc<[u8]>) -> Value {
844 Value::Bytes(x.as_ref().into())
845 }
846}
847
848impl From<Rc<[u8]>> for Value {
849 fn from(x: Rc<[u8]>) -> Value {
850 Value::Bytes(x.as_ref().into())
851 }
852}
853
854impl From<Vec<u8>> for Value {
855 fn from(x: Vec<u8>) -> Value {
856 Value::Bytes(x)
857 }
858}
859
860impl<'a> From<&'a str> for Value {
861 fn from(x: &'a str) -> Value {
862 let string: String = x.into();
863 Value::Bytes(string.into_bytes())
864 }
865}
866
867impl From<Box<str>> for Value {
868 fn from(x: Box<str>) -> Value {
869 Value::Bytes(String::from(x).into_bytes())
870 }
871}
872
873impl From<Arc<str>> for Value {
874 fn from(x: Arc<str>) -> Value {
875 Value::Bytes(x.as_ref().as_bytes().into())
876 }
877}
878
879impl From<Rc<str>> for Value {
880 fn from(x: Rc<str>) -> Value {
881 Value::Bytes(x.as_ref().as_bytes().into())
882 }
883}
884
885impl<'a, T: ToOwned> From<Cow<'a, T>> for Value
886where
887 T::Owned: Into<Value>,
888 &'a T: Into<Value>,
889{
890 fn from(x: Cow<'a, T>) -> Value {
891 match x {
892 Cow::Borrowed(x) => x.into(),
893 Cow::Owned(x) => x.into(),
894 }
895 }
896}
897
898impl From<String> for Value {
899 fn from(x: String) -> Value {
900 Value::Bytes(x.into_bytes())
901 }
902}
903
904impl<const N: usize> From<[u8; N]> for Value {
905 fn from(x: [u8; N]) -> Value {
906 Value::Bytes(x.to_vec())
907 }
908}
909
910#[cfg(test)]
911mod tests {
912 use super::*;
913 use proptest::prelude::*;
914
915 macro_rules! signed_primitive_roundtrip {
916 ($t:ty, $name:ident) => {
917 proptest! {
918 #[test]
919 fn $name(n: $t) {
920 let val = Value::Int(n as i64);
921 let val_bytes = Value::Bytes(n.to_string().into());
922 assert_eq!(Value::from(from_value::<$t>(val.clone())), val);
923 assert_eq!(Value::from(from_value::<$t>(val_bytes.clone())), val);
924 if n >= 0 {
925 let val_uint = Value::UInt(n as u64);
926 assert_eq!(Value::from(from_value::<$t>(val_uint.clone())), val);
927 }
928 }
929 }
930 };
931 }
932
933 macro_rules! unsigned_primitive_roundtrip {
934 ($t:ty, $name:ident) => {
935 proptest! {
936 #[test]
937 fn $name(n: $t) {
938 let val = Value::UInt(n as u64);
939 let val_bytes = Value::Bytes(n.to_string().into());
940 assert_eq!(Value::from(from_value::<$t>(val.clone())), val);
941 assert_eq!(Value::from(from_value::<$t>(val_bytes.clone())), val);
942 if n as u64 <= i64::max_value() as u64 {
943 let val_int = Value::Int(n as i64);
944 assert_eq!(Value::from(from_value::<$t>(val_int.clone())), val);
945 }
946 }
947 }
948 };
949 }
950
951 proptest! {
952 #[test]
953 fn bytes_roundtrip(s: Vec<u8>) {
954 let val = Value::Bytes(s);
955 assert_eq!(Value::from(from_value::<Vec<u8>>(val.clone())), val);
956 }
957
958 #[test]
959 fn string_roundtrip(s: String) {
960 let val = Value::Bytes(s.as_bytes().to_vec());
961 assert_eq!(Value::from(from_value::<String>(val.clone())), val);
962 }
963
964 #[test]
965 fn parse_mysql_time_string_parses_valid_time(
966 s in r"-?[0-8][0-9][0-9]:[0-5][0-9]:[0-5][0-9](\.[0-9]{1,6})?"
967 ) {
968 parse_mysql_time_string(s.as_bytes()).unwrap();
969 }
973
974 #[test]
975 fn parse_mysql_time_string_parses_correctly(
976 sign in 0..2,
977 h in 0u32..900,
978 m in 0u8..59,
979 s in 0u8..59,
980 have_us in 0..2,
981 us in 0u32..1000000,
982 ) {
983 let time_string = format!(
984 "{}{:02}:{:02}:{:02}{}",
985 if sign == 1 { "-" } else { "" },
986 h, m, s,
987 if have_us == 1 {
988 format!(".{:06}", us)
989 } else {
990 "".into()
991 }
992 );
993 let time = parse_mysql_time_string(time_string.as_bytes()).unwrap();
994 assert_eq!(time, (sign == 1, h, m, s, if have_us == 1 { us } else { 0 }));
995
996 }
1000
1001 #[test]
1002 fn parse_int_as_bool(n: i64) {
1003 let val = Value::Int(n);
1004 if n == 0 {
1005 assert_eq!(from_value::<bool>(val), false);
1006 } else {
1007 assert_eq!(from_value::<bool>(val), true);
1008 }
1009 }
1010
1011 #[test]
1012 fn parse_uint_as_bool(n: u64) {
1013 let val = Value::UInt(n);
1014 if n == 0 {
1015 assert_eq!(from_value::<bool>(val), false);
1016 } else {
1017 assert_eq!(from_value::<bool>(val), true);
1018 }
1019 }
1020
1021 #[test]
1022 fn i128_roundtrip(
1023 bytes_pos in r"16[0-9]{37}",
1024 bytes_neg in r"-16[0-9]{37}",
1025 uint in (i64::max_value() as u64 + 1)..u64::max_value(),
1026 int: i64,
1027 ) {
1028 let val_bytes_pos = Value::Bytes(bytes_pos.as_bytes().into());
1029 let val_bytes_neg = Value::Bytes(bytes_neg.as_bytes().into());
1030 let val_uint = Value::UInt(uint);
1031 let val_int = Value::Int(int);
1032
1033 assert_eq!(Value::from(from_value::<i128>(val_bytes_pos.clone())), val_bytes_pos);
1034 assert_eq!(Value::from(from_value::<i128>(val_bytes_neg.clone())), val_bytes_neg);
1035 assert_eq!(Value::from(from_value::<i128>(val_uint.clone())), val_uint);
1036 assert_eq!(Value::from(from_value::<i128>(val_int.clone())), val_int);
1037 }
1038
1039 #[test]
1040 fn u128_roundtrip(
1041 bytes in r"16[0-9]{37}",
1042 uint: u64,
1043 int in 0i64..i64::max_value(),
1044 ) {
1045 let val_bytes = Value::Bytes(bytes.as_bytes().into());
1046 let val_uint = Value::UInt(uint);
1047 let val_int = Value::Int(int);
1048
1049 assert_eq!(Value::from(from_value::<u128>(val_bytes.clone())), val_bytes);
1050 assert_eq!(Value::from(from_value::<u128>(val_uint.clone())), val_uint);
1051 assert_eq!(Value::from(from_value::<u128>(val_int)), Value::UInt(int as u64));
1052 }
1053
1054 #[test]
1055 fn f32_roundtrip(n: f32) {
1056 let val = Value::Float(n);
1057 let val_bytes = Value::Bytes(n.to_string().into());
1058 assert_eq!(Value::from(from_value::<f32>(val.clone())), val);
1059 assert_eq!(Value::from(from_value::<f32>(val_bytes)), val);
1060 }
1061
1062 #[test]
1063 fn f64_roundtrip(n: f64) {
1064 let val = Value::Double(n);
1065 let val_bytes = Value::Bytes(n.to_string().into());
1066 assert_eq!(Value::from(from_value::<f64>(val.clone())), val);
1067 assert_eq!(Value::from(from_value::<f64>(val_bytes)), val);
1068 }
1069 }
1070
1071 signed_primitive_roundtrip!(i8, i8_roundtrip);
1072 signed_primitive_roundtrip!(i16, i16_roundtrip);
1073 signed_primitive_roundtrip!(i32, i32_roundtrip);
1074 signed_primitive_roundtrip!(i64, i64_roundtrip);
1075
1076 unsigned_primitive_roundtrip!(u8, u8_roundtrip);
1077 unsigned_primitive_roundtrip!(u16, u16_roundtrip);
1078 unsigned_primitive_roundtrip!(u32, u32_roundtrip);
1079 unsigned_primitive_roundtrip!(u64, u64_roundtrip);
1080
1081 #[test]
1082 fn from_value_should_fail_on_integer_overflow() {
1083 let value = Value::Bytes(b"340282366920938463463374607431768211456"[..].into());
1084 assert!(from_value_opt::<u8>(value.clone()).is_err());
1085 assert!(from_value_opt::<i8>(value.clone()).is_err());
1086 assert!(from_value_opt::<u16>(value.clone()).is_err());
1087 assert!(from_value_opt::<i16>(value.clone()).is_err());
1088 assert!(from_value_opt::<u32>(value.clone()).is_err());
1089 assert!(from_value_opt::<i32>(value.clone()).is_err());
1090 assert!(from_value_opt::<u64>(value.clone()).is_err());
1091 assert!(from_value_opt::<i64>(value.clone()).is_err());
1092 assert!(from_value_opt::<u128>(value.clone()).is_err());
1093 assert!(from_value_opt::<i128>(value).is_err());
1094 }
1095
1096 #[test]
1097 fn from_value_should_fail_on_integer_underflow() {
1098 let value = Value::Bytes(b"-170141183460469231731687303715884105729"[..].into());
1099 assert!(from_value_opt::<u8>(value.clone()).is_err());
1100 assert!(from_value_opt::<i8>(value.clone()).is_err());
1101 assert!(from_value_opt::<u16>(value.clone()).is_err());
1102 assert!(from_value_opt::<i16>(value.clone()).is_err());
1103 assert!(from_value_opt::<u32>(value.clone()).is_err());
1104 assert!(from_value_opt::<i32>(value.clone()).is_err());
1105 assert!(from_value_opt::<u64>(value.clone()).is_err());
1106 assert!(from_value_opt::<i64>(value.clone()).is_err());
1107 assert!(from_value_opt::<u128>(value.clone()).is_err());
1108 assert!(from_value_opt::<i128>(value).is_err());
1109 }
1110
1111 #[cfg(feature = "nightly")]
1112 #[cfg(feature = "chrono")]
1113 #[bench]
1114 fn bench_parse_mysql_datetime_string(bencher: &mut test::Bencher) {
1115 let text = "1234-12-12 12:12:12.123456";
1116 bencher.bytes = text.len() as u64;
1117 bencher.iter(|| {
1118 parse_mysql_datetime_string(text.as_bytes()).unwrap();
1119 });
1120 }
1121
1122 #[cfg(feature = "nightly")]
1123 #[bench]
1124 fn bench_parse_mysql_time_string(bencher: &mut test::Bencher) {
1125 let text = "-012:34:56.012345";
1126 bencher.bytes = text.len() as u64;
1127 bencher.iter(|| {
1128 parse_mysql_time_string(text.as_bytes()).unwrap();
1129 });
1130 }
1131
1132 #[test]
1133 fn value_float_read_conversions_work() {
1134 let original_f32 = std::f32::consts::PI;
1135 let float_value = Value::Float(original_f32);
1136
1137 let converted_f32: f32 = f32::from_value_opt(float_value.clone()).unwrap();
1139 assert_eq!(converted_f32, original_f32);
1140
1141 let converted_f64: f64 = f64::from_value_opt(float_value).unwrap();
1143 assert_eq!(converted_f64, original_f32 as f64);
1144 }
1145
1146 #[test]
1147 fn value_double_read_conversions_work() {
1148 let original_f64 = std::f64::consts::PI;
1149 let double_value = Value::Double(original_f64);
1150
1151 let converted_f64: f64 = f64::from_value_opt(double_value.clone()).unwrap();
1153 assert_eq!(converted_f64, original_f64);
1154
1155 assert!(f32::from_value_opt(double_value).is_err());
1157 }
1158
1159 #[cfg(feature = "nightly")]
1160 #[bench]
1161 fn bench_parse_mysql_datetime_string_with_time(bencher: &mut test::Bencher) {
1162 let text = "1234-12-12 12:12:12.123456";
1163 bencher.bytes = text.len() as u64;
1164 bencher.iter(|| {
1165 parse_mysql_datetime_string_with_time(text.as_bytes()).unwrap();
1166 });
1167 }
1168
1169 #[cfg(feature = "nightly")]
1170 #[bench]
1171 fn bench_parse_mysql_time_string_with_time(bencher: &mut test::Bencher) {
1172 let text = "12:34:56.012345";
1173 bencher.bytes = text.len() as u64;
1174 bencher.iter(|| {
1175 parse_mysql_time_string_with_time(text.as_bytes()).unwrap();
1176 });
1177 }
1178}