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