1use std::borrow::Cow;
17use std::collections::HashMap;
18use std::fmt;
19use std::time::Duration;
20
21use bigdecimal::BigDecimal;
22use chrono::{
23 DateTime,
24 NaiveDate,
25 NaiveDateTime,
26 NaiveTime,
27 Utc,
28};
29use num_bigint::BigInt;
30use num_traits::ToPrimitive;
31use url::Url;
32
33use super::data_conversion_error::DataConversionError;
34use super::data_conversion_options::DataConversionOptions;
35use super::data_conversion_result::DataConversionResult;
36use super::data_convert_to::DataConvertTo;
37use super::duration_unit::DurationUnit;
38use crate::datatype::DataType;
39
40#[derive(Debug, Clone, PartialEq)]
74pub enum DataConverter<'a> {
75 Empty(DataType),
77 Bool(bool),
79 Char(char),
81 Int8(i8),
83 Int16(i16),
85 Int32(i32),
87 Int64(i64),
89 Int128(i128),
91 UInt8(u8),
93 UInt16(u16),
95 UInt32(u32),
97 UInt64(u64),
99 UInt128(u128),
101 IntSize(isize),
103 UIntSize(usize),
105 Float32(f32),
107 Float64(f64),
109 BigInteger(Cow<'a, BigInt>),
111 BigDecimal(Cow<'a, BigDecimal>),
113 String(Cow<'a, str>),
115 Date(NaiveDate),
117 Time(NaiveTime),
119 DateTime(NaiveDateTime),
121 Instant(DateTime<Utc>),
123 Duration(Duration),
125 Url(Cow<'a, Url>),
127 StringMap(Cow<'a, HashMap<String, String>>),
129 Json(Cow<'a, serde_json::Value>),
131}
132
133impl DataConverter<'_> {
134 #[inline]
151 pub fn to<T>(&self) -> DataConversionResult<T>
152 where
153 Self: DataConvertTo<T>,
154 {
155 self.to_with(&DataConversionOptions::default())
156 }
157
158 #[inline]
181 pub fn to_with<T>(&self, options: &DataConversionOptions) -> DataConversionResult<T>
182 where
183 Self: DataConvertTo<T>,
184 {
185 <Self as DataConvertTo<T>>::convert(self, options)
186 }
187
188 #[inline]
195 pub const fn data_type(&self) -> DataType {
196 match self {
197 DataConverter::Empty(data_type) => *data_type,
198 DataConverter::Bool(_) => DataType::Bool,
199 DataConverter::Char(_) => DataType::Char,
200 DataConverter::Int8(_) => DataType::Int8,
201 DataConverter::Int16(_) => DataType::Int16,
202 DataConverter::Int32(_) => DataType::Int32,
203 DataConverter::Int64(_) => DataType::Int64,
204 DataConverter::Int128(_) => DataType::Int128,
205 DataConverter::UInt8(_) => DataType::UInt8,
206 DataConverter::UInt16(_) => DataType::UInt16,
207 DataConverter::UInt32(_) => DataType::UInt32,
208 DataConverter::UInt64(_) => DataType::UInt64,
209 DataConverter::UInt128(_) => DataType::UInt128,
210 DataConverter::IntSize(_) => DataType::IntSize,
211 DataConverter::UIntSize(_) => DataType::UIntSize,
212 DataConverter::Float32(_) => DataType::Float32,
213 DataConverter::Float64(_) => DataType::Float64,
214 DataConverter::BigInteger(_) => DataType::BigInteger,
215 DataConverter::BigDecimal(_) => DataType::BigDecimal,
216 DataConverter::String(_) => DataType::String,
217 DataConverter::Date(_) => DataType::Date,
218 DataConverter::Time(_) => DataType::Time,
219 DataConverter::DateTime(_) => DataType::DateTime,
220 DataConverter::Instant(_) => DataType::Instant,
221 DataConverter::Duration(_) => DataType::Duration,
222 DataConverter::Url(_) => DataType::Url,
223 DataConverter::StringMap(_) => DataType::StringMap,
224 DataConverter::Json(_) => DataType::Json,
225 }
226 }
227
228 fn unsupported(&self, target_type: DataType) -> DataConversionError {
230 DataConversionError::ConversionFailed {
231 from: self.data_type(),
232 to: target_type,
233 }
234 }
235}
236
237macro_rules! impl_from_copy {
238 ($source_type:ty, $variant:ident) => {
239 impl<'a> From<$source_type> for DataConverter<'a> {
240 #[inline]
241 fn from(value: $source_type) -> Self {
242 DataConverter::$variant(value)
243 }
244 }
245
246 impl<'a> From<&'a $source_type> for DataConverter<'a> {
247 #[inline]
248 fn from(value: &'a $source_type) -> Self {
249 DataConverter::$variant(*value)
250 }
251 }
252 };
253}
254
255macro_rules! impl_from_cow {
256 ($source_type:ty, $variant:ident) => {
257 impl<'a> From<$source_type> for DataConverter<'a> {
258 #[inline]
259 fn from(value: $source_type) -> Self {
260 DataConverter::$variant(Cow::Owned(value))
261 }
262 }
263
264 impl<'a> From<&'a $source_type> for DataConverter<'a> {
265 #[inline]
266 fn from(value: &'a $source_type) -> Self {
267 DataConverter::$variant(Cow::Borrowed(value))
268 }
269 }
270 };
271}
272
273impl_from_copy!(bool, Bool);
274impl_from_copy!(char, Char);
275impl_from_copy!(i8, Int8);
276impl_from_copy!(i16, Int16);
277impl_from_copy!(i32, Int32);
278impl_from_copy!(i64, Int64);
279impl_from_copy!(i128, Int128);
280impl_from_copy!(u8, UInt8);
281impl_from_copy!(u16, UInt16);
282impl_from_copy!(u32, UInt32);
283impl_from_copy!(u64, UInt64);
284impl_from_copy!(u128, UInt128);
285impl_from_copy!(isize, IntSize);
286impl_from_copy!(usize, UIntSize);
287impl_from_copy!(f32, Float32);
288impl_from_copy!(f64, Float64);
289impl_from_copy!(NaiveDate, Date);
290impl_from_copy!(NaiveTime, Time);
291impl_from_copy!(NaiveDateTime, DateTime);
292impl_from_copy!(DateTime<Utc>, Instant);
293impl_from_copy!(Duration, Duration);
294
295impl_from_cow!(BigInt, BigInteger);
296impl_from_cow!(BigDecimal, BigDecimal);
297impl_from_cow!(Url, Url);
298impl_from_cow!(HashMap<String, String>, StringMap);
299impl_from_cow!(serde_json::Value, Json);
300
301impl<'a> From<&'a str> for DataConverter<'a> {
302 #[inline]
304 fn from(value: &'a str) -> Self {
305 DataConverter::String(Cow::Borrowed(value))
306 }
307}
308
309impl<'a> From<&'a String> for DataConverter<'a> {
310 #[inline]
312 fn from(value: &'a String) -> Self {
313 DataConverter::String(Cow::Borrowed(value.as_str()))
314 }
315}
316
317impl<'a> From<String> for DataConverter<'a> {
318 #[inline]
320 fn from(value: String) -> Self {
321 DataConverter::String(Cow::Owned(value))
322 }
323}
324
325fn parse_bool_string(value: &str, options: &DataConversionOptions) -> DataConversionResult<bool> {
327 let value = options.string.normalize(value)?;
328 if let Some(parsed) = options.boolean.parse(&value) {
329 Ok(parsed)
330 } else {
331 Err(DataConversionError::ConversionError(format!(
332 "Cannot convert '{value}' to boolean"
333 )))
334 }
335}
336
337fn parse_duration_string(
356 value: &str,
357 options: &DataConversionOptions,
358) -> DataConversionResult<Duration> {
359 let value = options.string.normalize(value)?;
360 let trimmed = value.trim();
361 if trimmed.is_empty() {
362 return Err(DataConversionError::ConversionError(
363 "Cannot convert empty string to Duration".to_string(),
364 ));
365 }
366 let (number, unit) = split_duration_number_and_unit(trimmed)?;
367 let value = number.parse::<u64>().map_err(|_| {
368 DataConversionError::ConversionError(format!(
369 "Cannot convert '{trimmed}' to Duration: invalid duration value"
370 ))
371 })?;
372 let unit = match unit {
373 Some(unit) => DurationUnit::from_suffix(unit).ok_or_else(|| {
374 DataConversionError::ConversionError(format!(
375 "Cannot convert '{trimmed}' to Duration: unsupported duration unit '{unit}'"
376 ))
377 })?,
378 None => options.duration.unit,
379 };
380 unit.duration_from_u64(value).map_err(|message| {
381 DataConversionError::ConversionError(format!(
382 "Cannot convert '{trimmed}' to Duration: {message}"
383 ))
384 })
385}
386
387fn split_duration_number_and_unit(text: &str) -> DataConversionResult<(&str, Option<&str>)> {
402 let Some(split_at) = text.find(|ch: char| !ch.is_ascii_digit()) else {
403 return Ok((text, None));
404 };
405 let (number, unit) = text.split_at(split_at);
406 if number.is_empty() {
407 return Err(DataConversionError::ConversionError(
408 "Cannot convert duration string: duration value is missing".to_string(),
409 ));
410 }
411 Ok((number, Some(unit)))
412}
413
414fn signed_integer_to_duration(
430 value: i128,
431 options: &DataConversionOptions,
432) -> DataConversionResult<Duration> {
433 if value < 0 {
434 return Err(DataConversionError::ConversionError(format!(
435 "Cannot convert {value} to Duration: duration value must be non-negative"
436 )));
437 }
438 let value = range_check(value, 0i128, u64::MAX as i128, "Duration")?;
439 options
440 .duration
441 .unit
442 .duration_from_u64(value as u64)
443 .map_err(|message| {
444 DataConversionError::ConversionError(format!(
445 "Cannot convert {value} to Duration: {message}"
446 ))
447 })
448}
449
450fn unsigned_integer_to_duration(
466 value: u128,
467 options: &DataConversionOptions,
468) -> DataConversionResult<Duration> {
469 let value = range_check(value, 0u128, u64::MAX as u128, "Duration")?;
470 options
471 .duration
472 .unit
473 .duration_from_u64(value as u64)
474 .map_err(|message| {
475 DataConversionError::ConversionError(format!(
476 "Cannot convert {value} to Duration: {message}"
477 ))
478 })
479}
480
481fn format_duration(duration: Duration, options: &DataConversionOptions) -> String {
494 let unit = options.duration.unit;
495 let value = unit.rounded_units(duration);
496 if options.duration.append_unit_suffix {
497 format!("{}{}", value, unit.suffix())
498 } else {
499 value.to_string()
500 }
501}
502
503fn range_check<T>(value: T, min: T, max: T, target: &str) -> DataConversionResult<T>
505where
506 T: PartialOrd + fmt::Display + Copy,
507{
508 if value < min || value > max {
509 Err(DataConversionError::ConversionError(format!(
510 "Cannot convert value to {target}: value must be in range [{min}, {max}]: actual {value}"
511 )))
512 } else {
513 Ok(value)
514 }
515}
516
517fn checked_float_to_i128(value: f64, source: &str, target: &str) -> DataConversionResult<i128> {
519 if !value.is_finite() {
520 return Err(DataConversionError::ConversionError(format!(
521 "Cannot convert non-finite {source} value to {target}"
522 )));
523 }
524 value.to_i128().ok_or_else(|| {
525 DataConversionError::ConversionError(format!("{source} value out of {target} range"))
526 })
527}
528
529fn checked_bigint_to_f32(value: &BigInt) -> DataConversionResult<f32> {
531 let converted = value.to_f32().unwrap_or(f32::INFINITY);
532 if converted.is_finite() {
533 Ok(converted)
534 } else {
535 Err(DataConversionError::ConversionError(
536 "BigInteger value out of f32 range".to_string(),
537 ))
538 }
539}
540
541fn checked_bigdecimal_to_f32(value: &BigDecimal) -> DataConversionResult<f32> {
543 let converted = value.to_f32().unwrap_or(f32::INFINITY);
544 if converted.is_finite() {
545 Ok(converted)
546 } else {
547 Err(DataConversionError::ConversionError(
548 "BigDecimal value out of f32 range".to_string(),
549 ))
550 }
551}
552
553fn checked_u128_to_f32(value: u128) -> DataConversionResult<f32> {
555 let converted = value as f32;
556 if converted.is_finite() {
557 Ok(converted)
558 } else {
559 Err(DataConversionError::ConversionError(
560 "u128 value out of f32 range".to_string(),
561 ))
562 }
563}
564
565fn checked_bigint_to_f64(value: &BigInt) -> DataConversionResult<f64> {
567 let converted = value.to_f64().unwrap_or(f64::INFINITY);
568 if converted.is_finite() {
569 Ok(converted)
570 } else {
571 Err(DataConversionError::ConversionError(
572 "BigInteger value out of f64 range".to_string(),
573 ))
574 }
575}
576
577fn checked_bigdecimal_to_f64(value: &BigDecimal) -> DataConversionResult<f64> {
579 let converted = value.to_f64().unwrap_or(f64::INFINITY);
580 if converted.is_finite() {
581 Ok(converted)
582 } else {
583 Err(DataConversionError::ConversionError(
584 "BigDecimal value out of f64 range".to_string(),
585 ))
586 }
587}
588
589fn convert_to_signed_integer(
591 source: &DataConverter<'_>,
592 options: &DataConversionOptions,
593 target_type: DataType,
594 target: &str,
595) -> DataConversionResult<i128> {
596 match source {
597 DataConverter::Bool(value) => Ok(if *value { 1 } else { 0 }),
598 DataConverter::Char(value) => Ok(*value as u32 as i128),
599 DataConverter::Int8(value) => Ok(*value as i128),
600 DataConverter::Int16(value) => Ok(*value as i128),
601 DataConverter::Int32(value) => Ok(*value as i128),
602 DataConverter::Int64(value) => Ok(*value as i128),
603 DataConverter::Int128(value) => Ok(*value),
604 DataConverter::IntSize(value) => Ok(*value as i128),
605 DataConverter::UInt8(value) => Ok(*value as i128),
606 DataConverter::UInt16(value) => Ok(*value as i128),
607 DataConverter::UInt32(value) => Ok(*value as i128),
608 DataConverter::UInt64(value) => Ok(*value as i128),
609 DataConverter::UInt128(value) => {
610 let checked = range_check(*value, 0u128, i128::MAX as u128, target)?;
611 Ok(checked as i128)
612 }
613 DataConverter::UIntSize(value) => Ok(*value as i128),
614 DataConverter::Float32(value) => checked_float_to_i128(*value as f64, "f32", target),
615 DataConverter::Float64(value) => checked_float_to_i128(*value, "f64", target),
616 DataConverter::String(value) => options
617 .string
618 .normalize(value.as_ref())?
619 .parse::<i128>()
620 .map_err(|_| {
621 DataConversionError::ConversionError(format!(
622 "Cannot convert '{}' to {target}",
623 value.as_ref()
624 ))
625 }),
626 DataConverter::Duration(value) => {
627 let units = options.duration.unit.rounded_units(*value);
628 let checked = range_check(units, 0u128, i128::MAX as u128, target)?;
629 Ok(checked as i128)
630 }
631 DataConverter::BigInteger(value) => value.as_ref().to_i128().ok_or_else(|| {
632 DataConversionError::ConversionError(format!("BigInteger value out of {target} range"))
633 }),
634 DataConverter::BigDecimal(value) => value.as_ref().to_i128().ok_or_else(|| {
635 DataConversionError::ConversionError(format!(
636 "BigDecimal value cannot be converted to {target}"
637 ))
638 }),
639 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
640 _ => Err(source.unsupported(target_type)),
641 }
642}
643
644fn convert_to_unsigned_integer(
646 source: &DataConverter<'_>,
647 options: &DataConversionOptions,
648 target_type: DataType,
649 target: &str,
650) -> DataConversionResult<u128> {
651 match source {
652 DataConverter::Bool(value) => Ok(if *value { 1 } else { 0 }),
653 DataConverter::Char(value) => Ok((*value as u32).into()),
654 DataConverter::Int8(value) => {
655 let checked = range_check(*value, 0i8, i8::MAX, target)?;
656 Ok(checked as u128)
657 }
658 DataConverter::Int16(value) => {
659 let checked = range_check(*value, 0i16, i16::MAX, target)?;
660 Ok(checked as u128)
661 }
662 DataConverter::Int32(value) => {
663 let checked = range_check(*value, 0i32, i32::MAX, target)?;
664 Ok(checked as u128)
665 }
666 DataConverter::Int64(value) => {
667 let checked = range_check(*value, 0i64, i64::MAX, target)?;
668 Ok(checked as u128)
669 }
670 DataConverter::Int128(value) => {
671 let checked = range_check(*value, 0i128, i128::MAX, target)?;
672 Ok(checked as u128)
673 }
674 DataConverter::IntSize(value) => {
675 let checked = range_check(*value, 0isize, isize::MAX, target)?;
676 Ok(checked as u128)
677 }
678 DataConverter::UInt8(value) => Ok((*value).into()),
679 DataConverter::UInt16(value) => Ok((*value).into()),
680 DataConverter::UInt32(value) => Ok((*value).into()),
681 DataConverter::UInt64(value) => Ok((*value).into()),
682 DataConverter::UInt128(value) => Ok(*value),
683 DataConverter::UIntSize(value) => Ok(*value as u128),
684 DataConverter::String(value) => options
685 .string
686 .normalize(value.as_ref())?
687 .parse::<u128>()
688 .map_err(|_| {
689 DataConversionError::ConversionError(format!(
690 "Cannot convert '{}' to {target}",
691 value.as_ref()
692 ))
693 }),
694 DataConverter::Duration(value) => Ok(options.duration.unit.rounded_units(*value)),
695 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
696 _ => Err(source.unsupported(target_type)),
697 }
698}
699
700impl DataConvertTo<String> for DataConverter<'_> {
701 fn convert(&self, options: &DataConversionOptions) -> DataConversionResult<String> {
703 match self {
704 DataConverter::String(value) => options.string.normalize(value.as_ref()),
705 DataConverter::Bool(value) => Ok(value.to_string()),
706 DataConverter::Char(value) => Ok(value.to_string()),
707 DataConverter::Int8(value) => Ok(value.to_string()),
708 DataConverter::Int16(value) => Ok(value.to_string()),
709 DataConverter::Int32(value) => Ok(value.to_string()),
710 DataConverter::Int64(value) => Ok(value.to_string()),
711 DataConverter::Int128(value) => Ok(value.to_string()),
712 DataConverter::UInt8(value) => Ok(value.to_string()),
713 DataConverter::UInt16(value) => Ok(value.to_string()),
714 DataConverter::UInt32(value) => Ok(value.to_string()),
715 DataConverter::UInt64(value) => Ok(value.to_string()),
716 DataConverter::UInt128(value) => Ok(value.to_string()),
717 DataConverter::IntSize(value) => Ok(value.to_string()),
718 DataConverter::UIntSize(value) => Ok(value.to_string()),
719 DataConverter::Float32(value) => Ok(value.to_string()),
720 DataConverter::Float64(value) => Ok(value.to_string()),
721 DataConverter::BigInteger(value) => Ok(value.to_string()),
722 DataConverter::BigDecimal(value) => Ok(value.to_string()),
723 DataConverter::Date(value) => Ok(value.to_string()),
724 DataConverter::Time(value) => Ok(value.to_string()),
725 DataConverter::DateTime(value) => Ok(value.to_string()),
726 DataConverter::Instant(value) => Ok(value.to_rfc3339()),
727 DataConverter::Duration(value) => Ok(format_duration(*value, options)),
728 DataConverter::Url(value) => Ok(value.to_string()),
729 DataConverter::StringMap(value) => match serde_json::to_string(value.as_ref()) {
730 Ok(value) => Ok(value),
731 Err(error) => Err(DataConversionError::JsonSerializationError(
732 error.to_string(),
733 )),
734 },
735 DataConverter::Json(value) => match serde_json::to_string(value.as_ref()) {
736 Ok(value) => Ok(value),
737 Err(error) => Err(DataConversionError::JsonSerializationError(
738 error.to_string(),
739 )),
740 },
741 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
742 }
743 }
744}
745
746impl DataConvertTo<bool> for DataConverter<'_> {
747 fn convert(&self, options: &DataConversionOptions) -> DataConversionResult<bool> {
749 match self {
750 DataConverter::Bool(value) => Ok(*value),
751 DataConverter::Int8(value) => Ok(*value != 0),
752 DataConverter::Int16(value) => Ok(*value != 0),
753 DataConverter::Int32(value) => Ok(*value != 0),
754 DataConverter::Int64(value) => Ok(*value != 0),
755 DataConverter::Int128(value) => Ok(*value != 0),
756 DataConverter::UInt8(value) => Ok(*value != 0),
757 DataConverter::UInt16(value) => Ok(*value != 0),
758 DataConverter::UInt32(value) => Ok(*value != 0),
759 DataConverter::UInt64(value) => Ok(*value != 0),
760 DataConverter::UInt128(value) => Ok(*value != 0),
761 DataConverter::String(value) => parse_bool_string(value.as_ref(), options),
762 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
763 _ => Err(self.unsupported(DataType::Bool)),
764 }
765 }
766}
767
768impl DataConvertTo<char> for DataConverter<'_> {
769 fn convert(&self, _options: &DataConversionOptions) -> DataConversionResult<char> {
771 match self {
772 DataConverter::Char(value) => Ok(*value),
773 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
774 _ => Err(self.unsupported(DataType::Char)),
775 }
776 }
777}
778
779macro_rules! impl_signed_integer_converter {
780 ($target_type:ty, $data_type:expr, $target_name:expr, $min:expr, $max:expr) => {
781 impl DataConvertTo<$target_type> for DataConverter<'_> {
782 #[inline]
783 fn convert(
784 &self,
785 options: &DataConversionOptions,
786 ) -> DataConversionResult<$target_type> {
787 let value = convert_to_signed_integer(self, options, $data_type, $target_name)?;
788 let checked = range_check(value, $min as i128, $max as i128, $target_name)?;
789 Ok(checked as $target_type)
790 }
791 }
792 };
793}
794
795impl_signed_integer_converter!(i8, DataType::Int8, "i8", i8::MIN, i8::MAX);
796impl_signed_integer_converter!(i16, DataType::Int16, "i16", i16::MIN, i16::MAX);
797impl_signed_integer_converter!(i32, DataType::Int32, "i32", i32::MIN, i32::MAX);
798impl_signed_integer_converter!(i64, DataType::Int64, "i64", i64::MIN, i64::MAX);
799impl_signed_integer_converter!(isize, DataType::IntSize, "isize", isize::MIN, isize::MAX);
800
801impl DataConvertTo<i128> for DataConverter<'_> {
802 #[inline]
804 fn convert(&self, options: &DataConversionOptions) -> DataConversionResult<i128> {
805 convert_to_signed_integer(self, options, DataType::Int128, "i128")
806 }
807}
808
809macro_rules! impl_unsigned_integer_converter {
810 ($target_type:ty, $data_type:expr, $target_name:expr, $max:expr) => {
811 impl DataConvertTo<$target_type> for DataConverter<'_> {
812 #[inline]
813 fn convert(
814 &self,
815 options: &DataConversionOptions,
816 ) -> DataConversionResult<$target_type> {
817 let value = convert_to_unsigned_integer(self, options, $data_type, $target_name)?;
818 let checked = range_check(
819 value,
820 <$target_type>::MIN as u128,
821 $max as u128,
822 $target_name,
823 )?;
824 Ok(checked as $target_type)
825 }
826 }
827 };
828}
829
830impl_unsigned_integer_converter!(u8, DataType::UInt8, "u8", u8::MAX);
831impl_unsigned_integer_converter!(u16, DataType::UInt16, "u16", u16::MAX);
832impl_unsigned_integer_converter!(u32, DataType::UInt32, "u32", u32::MAX);
833impl_unsigned_integer_converter!(u64, DataType::UInt64, "u64", u64::MAX);
834impl_unsigned_integer_converter!(usize, DataType::UIntSize, "usize", usize::MAX);
835
836impl DataConvertTo<u128> for DataConverter<'_> {
837 #[inline]
839 fn convert(&self, options: &DataConversionOptions) -> DataConversionResult<u128> {
840 convert_to_unsigned_integer(self, options, DataType::UInt128, "u128")
841 }
842}
843
844impl DataConvertTo<f32> for DataConverter<'_> {
845 fn convert(&self, options: &DataConversionOptions) -> DataConversionResult<f32> {
847 match self {
848 DataConverter::Float32(value) => Ok(*value),
849 DataConverter::Float64(value) => {
850 if value.is_nan() || value.is_infinite() {
851 Ok(*value as f32)
852 } else {
853 let checked = range_check(*value, f32::MIN as f64, f32::MAX as f64, "f32")?;
854 Ok(checked as f32)
855 }
856 }
857 DataConverter::Bool(value) => Ok(if *value { 1.0 } else { 0.0 }),
858 DataConverter::Char(value) => Ok(*value as u32 as f32),
859 DataConverter::Int8(value) => Ok(*value as f32),
860 DataConverter::Int16(value) => Ok(*value as f32),
861 DataConverter::Int32(value) => Ok(*value as f32),
862 DataConverter::Int64(value) => Ok(*value as f32),
863 DataConverter::Int128(value) => Ok(*value as f32),
864 DataConverter::IntSize(value) => Ok(*value as f32),
865 DataConverter::UInt8(value) => Ok(*value as f32),
866 DataConverter::UInt16(value) => Ok(*value as f32),
867 DataConverter::UInt32(value) => Ok(*value as f32),
868 DataConverter::UInt64(value) => Ok(*value as f32),
869 DataConverter::UInt128(value) => checked_u128_to_f32(*value),
870 DataConverter::UIntSize(value) => Ok(*value as f32),
871 DataConverter::String(value) => options
872 .string
873 .normalize(value.as_ref())?
874 .parse::<f32>()
875 .map_err(|_| {
876 DataConversionError::ConversionError(format!(
877 "Cannot convert '{}' to f32",
878 value.as_ref()
879 ))
880 }),
881 DataConverter::BigInteger(value) => checked_bigint_to_f32(value.as_ref()),
882 DataConverter::BigDecimal(value) => checked_bigdecimal_to_f32(value.as_ref()),
883 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
884 _ => Err(self.unsupported(DataType::Float32)),
885 }
886 }
887}
888
889impl DataConvertTo<f64> for DataConverter<'_> {
890 fn convert(&self, options: &DataConversionOptions) -> DataConversionResult<f64> {
892 match self {
893 DataConverter::Float64(value) => Ok(*value),
894 DataConverter::Float32(value) => Ok(*value as f64),
895 DataConverter::Bool(value) => Ok(if *value { 1.0 } else { 0.0 }),
896 DataConverter::Char(value) => Ok(*value as u32 as f64),
897 DataConverter::Int8(value) => Ok(*value as f64),
898 DataConverter::Int16(value) => Ok(*value as f64),
899 DataConverter::Int32(value) => Ok(*value as f64),
900 DataConverter::Int64(value) => Ok(*value as f64),
901 DataConverter::Int128(value) => Ok(*value as f64),
902 DataConverter::IntSize(value) => Ok(*value as f64),
903 DataConverter::UInt8(value) => Ok(*value as f64),
904 DataConverter::UInt16(value) => Ok(*value as f64),
905 DataConverter::UInt32(value) => Ok(*value as f64),
906 DataConverter::UInt64(value) => Ok(*value as f64),
907 DataConverter::UInt128(value) => Ok(*value as f64),
908 DataConverter::UIntSize(value) => Ok(*value as f64),
909 DataConverter::String(value) => options
910 .string
911 .normalize(value.as_ref())?
912 .parse::<f64>()
913 .map_err(|_| {
914 DataConversionError::ConversionError(format!(
915 "Cannot convert '{}' to f64",
916 value.as_ref()
917 ))
918 }),
919 DataConverter::BigInteger(value) => checked_bigint_to_f64(value.as_ref()),
920 DataConverter::BigDecimal(value) => checked_bigdecimal_to_f64(value.as_ref()),
921 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
922 _ => Err(self.unsupported(DataType::Float64)),
923 }
924 }
925}
926
927macro_rules! impl_strict_copy_converter {
928 ($target_type:ty, $variant:ident, $data_type:expr) => {
929 impl DataConvertTo<$target_type> for DataConverter<'_> {
930 #[inline]
931 fn convert(
932 &self,
933 _options: &DataConversionOptions,
934 ) -> DataConversionResult<$target_type> {
935 match self {
936 DataConverter::$variant(value) => Ok(*value),
937 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
938 _ => Err(self.unsupported($data_type)),
939 }
940 }
941 }
942 };
943}
944
945macro_rules! impl_strict_cow_converter {
946 ($target_type:ty, $variant:ident, $data_type:expr) => {
947 impl DataConvertTo<$target_type> for DataConverter<'_> {
948 #[inline]
949 fn convert(
950 &self,
951 _options: &DataConversionOptions,
952 ) -> DataConversionResult<$target_type> {
953 match self {
954 DataConverter::$variant(value) => Ok(value.as_ref().clone()),
955 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
956 _ => Err(self.unsupported($data_type)),
957 }
958 }
959 }
960 };
961}
962
963impl_strict_copy_converter!(NaiveDate, Date, DataType::Date);
964impl_strict_copy_converter!(NaiveTime, Time, DataType::Time);
965impl_strict_copy_converter!(NaiveDateTime, DateTime, DataType::DateTime);
966impl_strict_copy_converter!(DateTime<Utc>, Instant, DataType::Instant);
967impl_strict_cow_converter!(BigInt, BigInteger, DataType::BigInteger);
968impl_strict_cow_converter!(BigDecimal, BigDecimal, DataType::BigDecimal);
969impl_strict_cow_converter!(HashMap<String, String>, StringMap, DataType::StringMap);
970
971impl DataConvertTo<Duration> for DataConverter<'_> {
972 fn convert(&self, options: &DataConversionOptions) -> DataConversionResult<Duration> {
974 match self {
975 DataConverter::Duration(value) => Ok(*value),
976 DataConverter::Int8(value) => signed_integer_to_duration((*value).into(), options),
977 DataConverter::Int16(value) => signed_integer_to_duration((*value).into(), options),
978 DataConverter::Int32(value) => signed_integer_to_duration((*value).into(), options),
979 DataConverter::Int64(value) => signed_integer_to_duration((*value).into(), options),
980 DataConverter::Int128(value) => signed_integer_to_duration(*value, options),
981 DataConverter::IntSize(value) => signed_integer_to_duration(*value as i128, options),
982 DataConverter::UInt8(value) => unsigned_integer_to_duration((*value).into(), options),
983 DataConverter::UInt16(value) => unsigned_integer_to_duration((*value).into(), options),
984 DataConverter::UInt32(value) => unsigned_integer_to_duration((*value).into(), options),
985 DataConverter::UInt64(value) => unsigned_integer_to_duration((*value).into(), options),
986 DataConverter::UInt128(value) => unsigned_integer_to_duration(*value, options),
987 DataConverter::UIntSize(value) => unsigned_integer_to_duration(*value as u128, options),
988 DataConverter::BigInteger(value) => value.as_ref().to_u64().map_or_else(
989 || {
990 Err(DataConversionError::ConversionError(
991 "Cannot convert BigInteger to Duration: value must be a non-negative u64"
992 .to_string(),
993 ))
994 },
995 |value| {
996 options
997 .duration
998 .unit
999 .duration_from_u64(value)
1000 .map_err(|message| {
1001 DataConversionError::ConversionError(format!(
1002 "Cannot convert BigInteger to Duration: {message}"
1003 ))
1004 })
1005 },
1006 ),
1007 DataConverter::String(value) => parse_duration_string(value.as_ref(), options),
1008 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
1009 _ => Err(self.unsupported(DataType::Duration)),
1010 }
1011 }
1012}
1013
1014impl DataConvertTo<Url> for DataConverter<'_> {
1015 fn convert(&self, options: &DataConversionOptions) -> DataConversionResult<Url> {
1017 match self {
1018 DataConverter::Url(value) => Ok(value.as_ref().clone()),
1019 DataConverter::String(value) => {
1020 let value = options.string.normalize(value.as_ref())?;
1021 Url::parse(&value).map_err(|error| {
1022 DataConversionError::ConversionError(format!(
1023 "Cannot convert '{value}' to Url: {error}"
1024 ))
1025 })
1026 }
1027 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
1028 _ => Err(self.unsupported(DataType::Url)),
1029 }
1030 }
1031}
1032
1033impl DataConvertTo<serde_json::Value> for DataConverter<'_> {
1034 fn convert(&self, options: &DataConversionOptions) -> DataConversionResult<serde_json::Value> {
1036 match self {
1037 DataConverter::Json(value) => Ok(value.as_ref().clone()),
1038 DataConverter::String(value) => {
1039 let value = options.string.normalize(value.as_ref())?;
1040 serde_json::from_str(&value).map_err(|error| {
1041 DataConversionError::JsonDeserializationError(error.to_string())
1042 })
1043 }
1044 DataConverter::StringMap(value) => match serde_json::to_value(value.as_ref()) {
1045 Ok(value) => Ok(value),
1046 Err(error) => Err(DataConversionError::JsonSerializationError(
1047 error.to_string(),
1048 )),
1049 },
1050 DataConverter::Empty(_) => Err(DataConversionError::NoValue),
1051 _ => Err(self.unsupported(DataType::Json)),
1052 }
1053 }
1054}