use bigdecimal::BigDecimal;
use chrono::NaiveDate;
use num_bigint::BigInt;
use qubit_datatype::{
BlankStringPolicy,
BooleanConversionOptions,
DataConversionOptions,
DataType,
StringConversionOptions,
};
use qubit_value::{
Value,
ValueError,
};
use std::str::FromStr;
#[test]
fn test_value_type_conversion() {
let v = Value::Int32(42);
assert_eq!(v.to::<i64>().unwrap(), 42i64);
assert_eq!(v.to::<f64>().unwrap(), 42.0f64);
assert_eq!(v.to::<String>().unwrap(), "42");
}
#[test]
fn test_value_bool_conversion() {
let v1 = Value::Int32(1);
assert!(v1.to::<bool>().unwrap());
let v2 = Value::Int32(0);
assert!(!v2.to::<bool>().unwrap());
let v3 = Value::String("true".to_string());
assert!(v3.to::<bool>().unwrap());
}
#[test]
fn test_value_bool_conversion_accepts_config_bool_strings() {
let truthy_values = ["1", "true", "TRUE", "True", " true "];
for raw in truthy_values {
let value = Value::String(raw.to_string());
assert!(
value.to::<bool>().unwrap(),
"expected '{raw}' to convert to true"
);
}
let falsy_values = ["0", "false", "FALSE", "False", " false "];
for raw in falsy_values {
let value = Value::String(raw.to_string());
assert!(
!value.to::<bool>().unwrap(),
"expected '{raw}' to convert to false"
);
}
}
#[test]
fn test_value_to_with_applies_common_conversion_options() {
let options = DataConversionOptions::default()
.with_string_options(
StringConversionOptions::default()
.with_trim(true)
.with_blank_string_policy(BlankStringPolicy::TreatAsMissing),
)
.with_boolean_options(
BooleanConversionOptions::strict()
.with_true_literal("enabled")
.with_false_literal("disabled"),
);
let enabled = Value::String(" enabled ".to_string())
.to_with::<bool>(&options)
.expect("custom boolean literal should parse");
assert!(enabled);
let port = Value::String(" 8080 ".to_string())
.to_with::<u16>(&options)
.expect("trimmed numeric string should parse");
assert_eq!(port, 8080);
let blank = Value::String(" ".to_string()).to_with::<String>(&options);
assert!(matches!(blank, Err(ValueError::NoValue)));
}
#[test]
fn test_value_datetime_to_string() {
use chrono::{
NaiveDate,
NaiveTime,
Utc,
};
let date = NaiveDate::from_ymd_opt(2024, 1, 15).unwrap();
let value = Value::Date(date);
let str_repr = value.to::<String>().unwrap();
assert_eq!(str_repr, "2024-01-15");
let time = NaiveTime::from_hms_opt(14, 30, 45).unwrap();
let value = Value::Time(time);
let str_repr = value.to::<String>().unwrap();
assert_eq!(str_repr, "14:30:45");
let datetime = NaiveDate::from_ymd_opt(2024, 1, 15)
.unwrap()
.and_hms_opt(14, 30, 45)
.unwrap();
let value = Value::DateTime(datetime);
let str_repr = value.to::<String>().unwrap();
assert_eq!(str_repr, "2024-01-15 14:30:45");
let instant = Utc::now();
let value = Value::Instant(instant);
let str_repr = value.to::<String>().unwrap();
assert!(str_repr.contains('T')); }
#[test]
fn test_value_as_bool_all_branches() {
assert!(Value::Int8(1).to::<bool>().unwrap());
assert!(!Value::Int8(0).to::<bool>().unwrap());
assert!(Value::Int16(1).to::<bool>().unwrap());
assert!(!Value::Int16(0).to::<bool>().unwrap());
assert!(Value::Int64(1).to::<bool>().unwrap());
assert!(!Value::Int64(0).to::<bool>().unwrap());
assert!(Value::Int128(1).to::<bool>().unwrap());
assert!(!Value::Int128(0).to::<bool>().unwrap());
assert!(Value::UInt8(1).to::<bool>().unwrap());
assert!(!Value::UInt8(0).to::<bool>().unwrap());
assert!(Value::UInt16(1).to::<bool>().unwrap());
assert!(!Value::UInt16(0).to::<bool>().unwrap());
assert!(Value::UInt32(1).to::<bool>().unwrap());
assert!(!Value::UInt32(0).to::<bool>().unwrap());
assert!(Value::UInt64(1).to::<bool>().unwrap());
assert!(!Value::UInt64(0).to::<bool>().unwrap());
assert!(Value::UInt128(1).to::<bool>().unwrap());
assert!(!Value::UInt128(0).to::<bool>().unwrap());
let value = Value::String("invalid".to_string());
assert!(value.to::<bool>().is_err());
let value = Value::Empty(DataType::Bool);
assert!(matches!(value.to::<bool>(), Err(ValueError::NoValue)));
let value = Value::Char('a');
assert!(matches!(
value.to::<bool>(),
Err(ValueError::ConversionFailed { .. })
));
}
#[test]
fn test_value_as_int32_all_branches() {
assert_eq!(Value::Int8(42).to::<i32>().unwrap(), 42);
assert_eq!(Value::Int16(1000).to::<i32>().unwrap(), 1000);
assert_eq!(Value::Int32(100000).to::<i32>().unwrap(), 100000);
assert_eq!(Value::Int64(42).to::<i32>().unwrap(), 42);
let value = Value::Int64(i64::MAX);
assert!(value.to::<i32>().is_err());
assert_eq!(Value::Int128(42).to::<i32>().unwrap(), 42);
let value = Value::Int128(i128::MAX);
assert!(value.to::<i32>().is_err());
assert_eq!(Value::UInt8(42).to::<i32>().unwrap(), 42);
assert_eq!(Value::UInt16(1000).to::<i32>().unwrap(), 1000);
assert_eq!(Value::UInt32(42).to::<i32>().unwrap(), 42);
let value = Value::UInt32(u32::MAX);
assert!(value.to::<i32>().is_err());
assert_eq!(
Value::String("12345".to_string()).to::<i32>().unwrap(),
12345
);
let value = Value::String("invalid".to_string());
assert!(value.to::<i32>().is_err());
let value = Value::Empty(DataType::Int32);
assert!(matches!(value.to::<i32>(), Err(ValueError::NoValue)));
let value = Value::Bool(true);
assert_eq!(value.to::<i32>().unwrap(), 1);
let value = Value::Bool(false);
assert_eq!(value.to::<i32>().unwrap(), 0);
let value = Value::Char('A');
assert_eq!(value.to::<i32>().unwrap(), 65);
let value = Value::Float32(42.7);
assert_eq!(value.to::<i32>().unwrap(), 42);
let value = Value::Float64(99.9);
assert_eq!(value.to::<i32>().unwrap(), 99);
let value = Value::BigDecimal(BigDecimal::from(123));
assert_eq!(value.to::<i32>().unwrap(), 123);
let value = Value::Date(NaiveDate::from_ymd_opt(2024, 1, 1).unwrap());
assert!(matches!(
value.to::<i32>(),
Err(ValueError::ConversionFailed { .. })
));
}
#[test]
fn test_value_as_int64_all_branches() {
assert_eq!(Value::Int8(42).to::<i64>().unwrap(), 42);
assert_eq!(Value::Int16(1000).to::<i64>().unwrap(), 1000);
assert_eq!(Value::Int32(100000).to::<i64>().unwrap(), 100000);
assert_eq!(Value::Int64(1000000).to::<i64>().unwrap(), 1000000);
assert_eq!(Value::Int128(42).to::<i64>().unwrap(), 42);
let value = Value::Int128(i128::MAX);
assert!(value.to::<i64>().is_err());
assert_eq!(Value::UInt8(42).to::<i64>().unwrap(), 42);
assert_eq!(Value::UInt16(1000).to::<i64>().unwrap(), 1000);
assert_eq!(Value::UInt32(100000).to::<i64>().unwrap(), 100000);
assert_eq!(Value::UInt64(42).to::<i64>().unwrap(), 42);
let value = Value::UInt64(u64::MAX);
assert!(value.to::<i64>().is_err());
assert_eq!(
Value::String("123456789".to_string()).to::<i64>().unwrap(),
123456789
);
let value = Value::Empty(DataType::Int64);
assert!(matches!(value.to::<i64>(), Err(ValueError::NoValue)));
}
#[test]
fn test_value_as_float64_all_branches() {
assert_eq!(Value::Float32(3.5).to::<f64>().unwrap(), 3.5f32 as f64);
assert_eq!(Value::Float64(2.5).to::<f64>().unwrap(), 2.5);
assert_eq!(Value::Int8(42).to::<f64>().unwrap(), 42.0);
assert_eq!(Value::Int16(1000).to::<f64>().unwrap(), 1000.0);
assert_eq!(Value::Int32(100000).to::<f64>().unwrap(), 100000.0);
assert_eq!(Value::Int64(1000000).to::<f64>().unwrap(), 1000000.0);
assert_eq!(Value::UInt8(42).to::<f64>().unwrap(), 42.0);
assert_eq!(Value::UInt16(1000).to::<f64>().unwrap(), 1000.0);
assert_eq!(Value::UInt32(100000).to::<f64>().unwrap(), 100000.0);
assert_eq!(Value::UInt64(1000000).to::<f64>().unwrap(), 1000000.0);
assert_eq!(Value::String("3.5".to_string()).to::<f64>().unwrap(), 3.5);
let value = Value::String("invalid".to_string());
assert!(value.to::<f64>().is_err());
let value = Value::Empty(DataType::Float64);
assert!(matches!(value.to::<f64>(), Err(ValueError::NoValue)));
let value = Value::Bool(true);
assert_eq!(value.to::<f64>().unwrap(), 1.0);
let value = Value::Bool(false);
assert_eq!(value.to::<f64>().unwrap(), 0.0);
let value = Value::Char('A');
assert_eq!(value.to::<f64>().unwrap(), 65.0);
let value = Value::Int128(123);
assert_eq!(value.to::<f64>().unwrap(), 123.0);
let value = Value::UInt128(456);
assert_eq!(value.to::<f64>().unwrap(), 456.0);
let value = Value::Date(NaiveDate::from_ymd_opt(2024, 1, 1).unwrap());
assert!(matches!(
value.to::<f64>(),
Err(ValueError::ConversionFailed { .. })
));
}
#[test]
fn test_value_as_string_all_types() {
assert_eq!(Value::Bool(true).to::<String>().unwrap(), "true");
assert_eq!(Value::Bool(false).to::<String>().unwrap(), "false");
assert_eq!(Value::Char('A').to::<String>().unwrap(), "A");
assert_eq!(Value::Int8(42).to::<String>().unwrap(), "42");
assert_eq!(Value::Int16(1000).to::<String>().unwrap(), "1000");
assert_eq!(Value::Int32(100000).to::<String>().unwrap(), "100000");
assert_eq!(Value::Int64(1000000).to::<String>().unwrap(), "1000000");
assert_eq!(
Value::Int128(123456789).to::<String>().unwrap(),
"123456789"
);
assert_eq!(Value::UInt8(42).to::<String>().unwrap(), "42");
assert_eq!(Value::UInt16(1000).to::<String>().unwrap(), "1000");
assert_eq!(Value::UInt32(100000).to::<String>().unwrap(), "100000");
assert_eq!(Value::UInt64(1000000).to::<String>().unwrap(), "1000000");
assert_eq!(
Value::UInt128(123456789).to::<String>().unwrap(),
"123456789"
);
assert!(
Value::Float32(3.5)
.to::<String>()
.unwrap()
.starts_with("3.5")
);
assert!(
Value::Float64(2.5)
.to::<String>()
.unwrap()
.starts_with("2.5")
);
assert_eq!(
Value::String("hello".to_string()).to::<String>().unwrap(),
"hello"
);
let value = Value::Empty(DataType::String);
assert!(matches!(value.to::<String>(), Err(ValueError::NoValue)));
}
#[test]
fn test_value_as_int32_uint64_conversion() {
let value = Value::UInt64(100);
assert_eq!(value.to::<i32>().unwrap(), 100);
let value = Value::UInt64(u64::MAX);
assert!(value.to::<i32>().is_err());
let value = Value::UInt128(200);
assert_eq!(value.to::<i32>().unwrap(), 200);
let value = Value::UInt128(u128::MAX);
assert!(value.to::<i32>().is_err());
}
#[test]
fn test_value_as_int64_uint128_conversion() {
let value = Value::UInt128(1000);
assert_eq!(value.to::<i64>().unwrap(), 1000);
let value = Value::UInt128(u128::MAX);
assert!(value.to::<i64>().is_err());
let value = Value::String("not a number".to_string());
assert!(value.to::<i64>().is_err());
}
#[test]
fn test_value_as_float64_conversions() {
let value = Value::Int128(999999);
assert_eq!(value.to::<f64>().unwrap(), 999999.0);
let value = Value::UInt128(123456);
assert_eq!(value.to::<f64>().unwrap(), 123456.0);
let value = Value::Bool(true);
assert_eq!(value.to::<f64>().unwrap(), 1.0);
let value = Value::Bool(false);
assert_eq!(value.to::<f64>().unwrap(), 0.0);
let value = Value::Char('B');
assert_eq!(value.to::<f64>().unwrap(), 66.0);
let value = Value::String("invalid number".to_string());
assert!(value.to::<f64>().is_err());
}
#[test]
fn test_big_type_conversions_for_coverage() {
use bigdecimal::BigDecimal;
use num_bigint::BigInt;
use std::f64;
use std::str::FromStr;
let v = Value::BigInteger(BigInt::from(123));
assert_eq!(v.to::<i32>().unwrap(), 123);
let v_overflow = Value::BigInteger(BigInt::from(i64::MAX));
assert!(v_overflow.to::<i32>().is_err());
let v = Value::BigInteger(BigInt::from(123456i64));
assert_eq!(v.to::<i64>().unwrap(), 123456i64);
let v_overflow = Value::BigInteger(BigInt::from_str("123456789012345678901234567890").unwrap());
assert!(v_overflow.to::<i64>().is_err());
let v = Value::BigInteger(BigInt::from(12345));
assert!((v.to::<f64>().unwrap() - 12345.0).abs() < f64::EPSILON);
let large_big_int_str = "1".repeat(400);
let v_overflow = Value::BigInteger(BigInt::from_str(&large_big_int_str).unwrap());
assert!(v_overflow.to::<f64>().is_err());
let v = Value::BigDecimal(BigDecimal::from_str("123.456").unwrap());
assert!((v.to::<f64>().unwrap() - 123.456).abs() < f64::EPSILON);
let v_overflow = Value::BigDecimal(BigDecimal::from_str("1.0e400").unwrap());
assert!(v_overflow.to::<f64>().is_err());
}
#[test]
fn test_as_bool_string_conversion_error() {
let value = Value::String("not_a_bool".to_string());
match value.to::<bool>() {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("Cannot convert"));
assert!(msg.contains("not_a_bool"));
assert!(msg.contains("to boolean"));
}
_ => panic!("Expected ConversionError"),
}
let value = Value::String("".to_string());
assert!(matches!(
value.to::<bool>(),
Err(ValueError::ConversionError(_))
));
let invalid_bools = vec!["yes", "no", "t", "f", "y", "n", "on", "off"];
for invalid in invalid_bools {
let value = Value::String(invalid.to_string());
assert!(matches!(
value.to::<bool>(),
Err(ValueError::ConversionError(_))
));
}
}
#[test]
fn test_as_int32_conversion_errors() {
let value = Value::Int64(i64::MAX);
match value.to::<i32>() {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i32"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for i64 overflow"),
}
let value = Value::Int128(i128::MAX);
match value.to::<i32>() {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i32"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for i128 overflow"),
}
let value = Value::UInt32(u32::MAX);
match value.to::<i32>() {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i32"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for u32 overflow"),
}
let value = Value::String("not_a_number".to_string());
match value.to::<i32>() {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("Cannot convert"));
assert!(msg.contains("not_a_number"));
assert!(msg.contains("i32"));
}
_ => panic!("Expected ConversionError for string parse failure"),
}
let value = Value::BigInteger(BigInt::from_str("999999999999999999999").unwrap());
match value.to::<i32>() {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i32"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for BigInteger overflow"),
}
}
#[test]
fn test_as_int64_conversion_errors() {
let value = Value::Int128(i128::MAX);
match value.to::<i64>() {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for i128 overflow"),
}
let value = Value::UInt64(u64::MAX);
match value.to::<i64>() {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for u64 overflow"),
}
let value = Value::String("invalid_number".to_string());
match value.to::<i64>() {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("Cannot convert"));
assert!(msg.contains("invalid_number"));
assert!(msg.contains("i64"));
}
_ => panic!("Expected ConversionError for string parse failure"),
}
let value = Value::BigInteger(BigInt::from_str("999999999999999999999999999999").unwrap());
match value.to::<i64>() {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for BigInteger overflow"),
}
}
#[test]
fn test_as_float64_conversion_errors() {
let value = Value::String("not_a_float".to_string());
match value.to::<f64>() {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("Cannot convert"));
assert!(msg.contains("not_a_float"));
assert!(msg.contains("f64"));
}
_ => panic!("Expected ConversionError for string parse failure"),
}
}
#[test]
fn test_as_int32_negative_i64_conversion() {
let value = Value::Int64(i64::MIN);
match value.to::<i32>() {
Err(ValueError::ConversionError(_)) => {
}
_ => panic!("Expected ConversionError for negative i64 overflow"),
}
}
#[test]
fn test_as_int32_negative_i128_conversion() {
let value = Value::Int128(i128::MIN);
match value.to::<i32>() {
Err(ValueError::ConversionError(_)) => {
}
_ => panic!("Expected ConversionError for negative i128 overflow"),
}
}
#[test]
fn test_as_int64_negative_i128_conversion() {
let value = Value::Int128(i128::MIN);
match value.to::<i64>() {
Err(ValueError::ConversionError(_)) => {
}
_ => panic!("Expected ConversionError for negative i128 overflow"),
}
}
#[test]
fn test_as_int32_small_uint64_success() {
let value = Value::UInt64(100);
assert_eq!(value.to::<i32>().unwrap(), 100);
let value = Value::UInt64(u64::MAX);
assert!(value.to::<i32>().is_err());
}
#[test]
fn test_as_int64_small_uint128_conversion_failed() {
let value = Value::UInt128(100);
assert_eq!(value.to::<i64>().unwrap(), 100);
let value = Value::UInt128(u128::MAX);
assert!(value.to::<i64>().is_err());
}
#[test]
fn test_as_float64_int128_conversion_failed() {
let value = Value::Int128(100);
assert_eq!(value.to::<f64>().unwrap(), 100.0);
let value = Value::Int128(i128::MAX);
assert!(value.to::<f64>().is_ok());
}
#[test]
fn test_as_float64_uint128_conversion_failed() {
let value = Value::UInt128(100);
assert_eq!(value.to::<f64>().unwrap(), 100.0);
let value = Value::UInt128(u128::MAX);
assert!(value.to::<f64>().is_ok());
}
#[test]
fn test_as_bool_direct_bool_type() {
let value_true = Value::Bool(true);
assert!(value_true.to::<bool>().unwrap());
let value_false = Value::Bool(false);
assert!(!value_false.to::<bool>().unwrap());
}
#[test]
fn test_as_bool_string_parse_error() {
let invalid_strings = vec![
"yes", "no", "t", "f", "y", "n", "on", "off", "", " ", "null", "None",
];
for invalid_str in invalid_strings {
let value = Value::String(invalid_str.to_string());
assert!(
value.to::<bool>().is_err(),
"String '{}' should not be able to convert to bool",
invalid_str
);
}
let value_true = Value::String("true".to_string());
assert!(value_true.to::<bool>().unwrap());
let value_false = Value::String("false".to_string());
assert!(!value_false.to::<bool>().unwrap());
}
#[test]
fn test_as_bool_all_unsupported_types() {
use chrono::{
NaiveDate,
NaiveTime,
Utc,
};
assert!(matches!(
Value::Char('a').to::<bool>(),
Err(ValueError::ConversionFailed { .. })
));
assert!(matches!(
Value::Float32(1.5).to::<bool>(),
Err(ValueError::ConversionFailed { .. })
));
assert!(matches!(
Value::Float64(2.5).to::<bool>(),
Err(ValueError::ConversionFailed { .. })
));
assert!(matches!(
Value::Date(NaiveDate::from_ymd_opt(2024, 1, 1).unwrap()).to::<bool>(),
Err(ValueError::ConversionFailed { .. })
));
assert!(matches!(
Value::Time(NaiveTime::from_hms_opt(12, 0, 0).unwrap()).to::<bool>(),
Err(ValueError::ConversionFailed { .. })
));
assert!(matches!(
Value::DateTime(
NaiveDate::from_ymd_opt(2024, 1, 1)
.unwrap()
.and_hms_opt(12, 0, 0)
.unwrap()
)
.to::<bool>(),
Err(ValueError::ConversionFailed { .. })
));
assert!(matches!(
Value::Instant(Utc::now()).to::<bool>(),
Err(ValueError::ConversionFailed { .. })
));
assert!(matches!(
Value::BigInteger(BigInt::from(123)).to::<bool>(),
Err(ValueError::ConversionFailed { .. })
));
assert!(matches!(
Value::BigDecimal(BigDecimal::from_str("123.45").unwrap()).to::<bool>(),
Err(ValueError::ConversionFailed { .. })
));
}
#[test]
fn test_as_int32_direct_int32_type() {
let value = Value::Int32(42);
assert_eq!(value.to::<i32>().unwrap(), 42);
let value_negative = Value::Int32(-100);
assert_eq!(value_negative.to::<i32>().unwrap(), -100);
let value_max = Value::Int32(i32::MAX);
assert_eq!(value_max.to::<i32>().unwrap(), i32::MAX);
let value_min = Value::Int32(i32::MIN);
assert_eq!(value_min.to::<i32>().unwrap(), i32::MIN);
}
#[test]
fn test_as_int32_int64_overflow_cases() {
let value_max = Value::Int64(i64::MAX);
assert!(matches!(
value_max.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value_min = Value::Int64(i64::MIN);
assert!(matches!(
value_min.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value_over_max = Value::Int64(i32::MAX as i64 + 1);
assert!(matches!(
value_over_max.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value_under_min = Value::Int64(i32::MIN as i64 - 1);
assert!(matches!(
value_under_min.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value_in_range = Value::Int64(1000);
assert_eq!(value_in_range.to::<i32>().unwrap(), 1000);
}
#[test]
fn test_as_int32_int128_overflow_cases() {
let value_max = Value::Int128(i128::MAX);
assert!(matches!(
value_max.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value_min = Value::Int128(i128::MIN);
assert!(matches!(
value_min.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value_over_max = Value::Int128(i32::MAX as i128 + 1);
assert!(matches!(
value_over_max.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value_in_range = Value::Int128(500);
assert_eq!(value_in_range.to::<i32>().unwrap(), 500);
}
#[test]
fn test_as_int32_uint32_overflow_cases() {
let value_max = Value::UInt32(u32::MAX);
assert!(matches!(
value_max.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value_over_max = Value::UInt32(i32::MAX as u32 + 1);
assert!(matches!(
value_over_max.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value_in_range = Value::UInt32(100);
assert_eq!(value_in_range.to::<i32>().unwrap(), 100);
let value_max_valid = Value::UInt32(i32::MAX as u32);
assert_eq!(value_max_valid.to::<i32>().unwrap(), i32::MAX);
}
#[test]
fn test_as_int32_string_parse_error() {
let value = Value::String("not_a_number".to_string());
assert!(matches!(
value.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("".to_string());
assert!(matches!(
value.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("123.45".to_string());
assert!(matches!(
value.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String(" 123 ".to_string());
assert!(matches!(
value.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("123abc".to_string());
assert!(matches!(
value.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("9999999999999999999".to_string());
assert!(matches!(
value.to::<i32>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("12345".to_string());
assert_eq!(value.to::<i32>().unwrap(), 12345);
let value_negative = Value::String("-9876".to_string());
assert_eq!(value_negative.to::<i32>().unwrap(), -9876);
}
#[test]
fn test_as_int64_direct_int64_type() {
let value = Value::Int64(123456789);
assert_eq!(value.to::<i64>().unwrap(), 123456789);
let value_negative = Value::Int64(-987654321);
assert_eq!(value_negative.to::<i64>().unwrap(), -987654321);
let value_max = Value::Int64(i64::MAX);
assert_eq!(value_max.to::<i64>().unwrap(), i64::MAX);
let value_min = Value::Int64(i64::MIN);
assert_eq!(value_min.to::<i64>().unwrap(), i64::MIN);
}
#[test]
fn test_as_int64_int128_overflow_cases() {
let value_max = Value::Int128(i128::MAX);
assert!(matches!(
value_max.to::<i64>(),
Err(ValueError::ConversionError(_))
));
let value_min = Value::Int128(i128::MIN);
assert!(matches!(
value_min.to::<i64>(),
Err(ValueError::ConversionError(_))
));
let value_over_max = Value::Int128(i64::MAX as i128 + 1);
assert!(matches!(
value_over_max.to::<i64>(),
Err(ValueError::ConversionError(_))
));
let value_under_min = Value::Int128(i64::MIN as i128 - 1);
assert!(matches!(
value_under_min.to::<i64>(),
Err(ValueError::ConversionError(_))
));
let value_in_range = Value::Int128(999999);
assert_eq!(value_in_range.to::<i64>().unwrap(), 999999);
}
#[test]
fn test_as_int64_uint64_overflow_cases() {
let value_max = Value::UInt64(u64::MAX);
assert!(matches!(
value_max.to::<i64>(),
Err(ValueError::ConversionError(_))
));
let value_over_max = Value::UInt64(i64::MAX as u64 + 1);
assert!(matches!(
value_over_max.to::<i64>(),
Err(ValueError::ConversionError(_))
));
let value_in_range = Value::UInt64(123456);
assert_eq!(value_in_range.to::<i64>().unwrap(), 123456);
let value_max_valid = Value::UInt64(i64::MAX as u64);
assert_eq!(value_max_valid.to::<i64>().unwrap(), i64::MAX);
}
#[test]
fn test_as_int64_string_parse_error() {
let value = Value::String("invalid_number".to_string());
assert!(matches!(
value.to::<i64>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("".to_string());
assert!(matches!(
value.to::<i64>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("456.789".to_string());
assert!(matches!(
value.to::<i64>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("99999999999999999999999999999".to_string());
assert!(matches!(
value.to::<i64>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("123456789".to_string());
assert_eq!(value.to::<i64>().unwrap(), 123456789);
let value_negative = Value::String("-987654321".to_string());
assert_eq!(value_negative.to::<i64>().unwrap(), -987654321);
}
#[test]
fn test_as_float64_direct_float64_type() {
let value = Value::Float64(3.5);
assert_eq!(value.to::<f64>().unwrap(), 3.5);
let value_negative = Value::Float64(-2.5);
assert_eq!(value_negative.to::<f64>().unwrap(), -2.5);
let value_zero = Value::Float64(0.0);
assert_eq!(value_zero.to::<f64>().unwrap(), 0.0);
let value_inf = Value::Float64(f64::INFINITY);
assert_eq!(value_inf.to::<f64>().unwrap(), f64::INFINITY);
let value_neg_inf = Value::Float64(f64::NEG_INFINITY);
assert_eq!(value_neg_inf.to::<f64>().unwrap(), f64::NEG_INFINITY);
let value_nan = Value::Float64(f64::NAN);
assert!(value_nan.to::<f64>().unwrap().is_nan());
}
#[test]
fn test_as_float64_string_parse_error() {
let value = Value::String("not_a_float".to_string());
assert!(matches!(
value.to::<f64>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("".to_string());
assert!(matches!(
value.to::<f64>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("12.34abc".to_string());
assert!(matches!(
value.to::<f64>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("12.34.56".to_string());
assert!(matches!(
value.to::<f64>(),
Err(ValueError::ConversionError(_))
));
let value = Value::String("3.5".to_string());
assert_eq!(value.to::<f64>().unwrap(), 3.5);
let value_negative = Value::String("-2.5".to_string());
assert_eq!(value_negative.to::<f64>().unwrap(), -2.5);
let value_scientific = Value::String("1.23e10".to_string());
assert_eq!(value_scientific.to::<f64>().unwrap(), 1.23e10);
}
#[test]
fn test_as_float64_biginteger_conversion_error() {
use std::str::FromStr;
let value = Value::BigInteger(BigInt::from(12345));
assert_eq!(value.to::<f64>().unwrap(), 12345.0);
let large_big_int = BigInt::from_str(&"9".repeat(400)).unwrap();
let value = Value::BigInteger(large_big_int);
assert!(value.to::<f64>().is_err());
let value_negative = Value::BigInteger(BigInt::from(-999999));
assert_eq!(value_negative.to::<f64>().unwrap(), -999999.0);
}
#[test]
fn test_as_float64_bigdecimal_conversion_error() {
use std::str::FromStr;
let value = Value::BigDecimal(BigDecimal::from_str("123.456").unwrap());
assert!((value.to::<f64>().unwrap() - 123.456).abs() < 1e-10);
let large_big_decimal = BigDecimal::from_str("1.0e400").unwrap();
let value = Value::BigDecimal(large_big_decimal);
assert!(value.to::<f64>().is_err());
let small_big_decimal = BigDecimal::from_str("-1.0e400").unwrap();
let value = Value::BigDecimal(small_big_decimal);
assert!(value.to::<f64>().is_err());
let value = Value::BigDecimal(BigDecimal::from_str("0.123456789012345").unwrap());
assert!((value.to::<f64>().unwrap() - 0.123456789012345).abs() < 1e-15);
}
#[test]
fn test_as_int32_all_unsigned_types() {
let value = Value::UInt8(255);
assert_eq!(value.to::<i32>().unwrap(), 255);
let value = Value::UInt16(65535);
assert_eq!(value.to::<i32>().unwrap(), 65535);
let value_ok = Value::UInt32(100);
assert_eq!(value_ok.to::<i32>().unwrap(), 100);
let value_overflow = Value::UInt32(u32::MAX);
assert!(value_overflow.to::<i32>().is_err());
let value_ok = Value::UInt64(200);
assert_eq!(value_ok.to::<i32>().unwrap(), 200);
let value_overflow = Value::UInt64(u64::MAX);
assert!(value_overflow.to::<i32>().is_err());
let value_ok = Value::UInt128(300);
assert_eq!(value_ok.to::<i32>().unwrap(), 300);
let value_overflow = Value::UInt128(u128::MAX);
assert!(value_overflow.to::<i32>().is_err());
}
#[test]
fn test_as_int64_all_unsigned_types() {
let value = Value::UInt8(255);
assert_eq!(value.to::<i64>().unwrap(), 255);
let value = Value::UInt16(65535);
assert_eq!(value.to::<i64>().unwrap(), 65535);
let value = Value::UInt32(u32::MAX);
assert_eq!(value.to::<i64>().unwrap(), u32::MAX as i64);
let value_ok = Value::UInt64(1000);
assert_eq!(value_ok.to::<i64>().unwrap(), 1000);
let value_overflow = Value::UInt64(u64::MAX);
assert!(value_overflow.to::<i64>().is_err());
let value_ok = Value::UInt128(2000);
assert_eq!(value_ok.to::<i64>().unwrap(), 2000);
let value_overflow = Value::UInt128(u128::MAX);
assert!(value_overflow.to::<i64>().is_err());
}
#[test]
fn test_as_float64_all_integer_types() {
assert_eq!(Value::Int8(127).to::<f64>().unwrap(), 127.0);
assert_eq!(Value::Int8(-128).to::<f64>().unwrap(), -128.0);
assert_eq!(Value::Int16(32767).to::<f64>().unwrap(), 32767.0);
assert_eq!(Value::Int16(-32768).to::<f64>().unwrap(), -32768.0);
assert_eq!(Value::Int32(i32::MAX).to::<f64>().unwrap(), i32::MAX as f64);
assert_eq!(Value::Int32(i32::MIN).to::<f64>().unwrap(), i32::MIN as f64);
assert_eq!(Value::Int64(i64::MAX).to::<f64>().unwrap(), i64::MAX as f64);
assert_eq!(Value::Int64(i64::MIN).to::<f64>().unwrap(), i64::MIN as f64);
assert_eq!(
Value::Int128(i128::MAX).to::<f64>().unwrap(),
i128::MAX as f64
);
assert_eq!(
Value::Int128(i128::MIN).to::<f64>().unwrap(),
i128::MIN as f64
);
assert_eq!(Value::UInt8(255).to::<f64>().unwrap(), 255.0);
assert_eq!(Value::UInt16(65535).to::<f64>().unwrap(), 65535.0);
assert_eq!(
Value::UInt32(u32::MAX).to::<f64>().unwrap(),
u32::MAX as f64
);
assert_eq!(
Value::UInt64(u64::MAX).to::<f64>().unwrap(),
u64::MAX as f64
);
assert_eq!(
Value::UInt128(u128::MAX).to::<f64>().unwrap(),
u128::MAX as f64
);
}
#[test]
fn test_as_string_direct_string_type() {
let value = Value::String("hello world".to_string());
assert_eq!(value.to::<String>().unwrap(), "hello world");
let value_empty = Value::String("".to_string());
assert_eq!(value_empty.to::<String>().unwrap(), "");
let value_unicode = Value::String("你好世界🌍".to_string());
assert_eq!(value_unicode.to::<String>().unwrap(), "你好世界🌍");
}
#[test]
fn test_conversion_with_edge_values() {
assert_eq!(Value::Int32(i32::MAX).to::<i64>().unwrap(), i32::MAX as i64);
assert_eq!(Value::Int32(i32::MIN).to::<i64>().unwrap(), i32::MIN as i64);
assert_eq!(Value::Int32(i32::MAX).to::<f64>().unwrap(), i32::MAX as f64);
assert_eq!(Value::Int32(i32::MIN).to::<f64>().unwrap(), i32::MIN as f64);
assert_eq!(Value::Int64(i64::MAX).to::<f64>().unwrap(), i64::MAX as f64);
assert_eq!(Value::Int64(i64::MIN).to::<f64>().unwrap(), i64::MIN as f64);
assert_eq!(
Value::UInt32(u32::MAX).to::<i64>().unwrap(),
u32::MAX as i64
);
assert_eq!(
Value::UInt32(u32::MAX).to::<f64>().unwrap(),
u32::MAX as f64
);
assert_eq!(
Value::Float32(f32::MAX).to::<f64>().unwrap(),
f32::MAX as f64
);
assert_eq!(
Value::Float32(f32::MIN).to::<f64>().unwrap(),
f32::MIN as f64
);
}
#[test]
fn test_as_int32_bigdecimal_out_of_range() {
use bigdecimal::BigDecimal;
use std::str::FromStr;
let huge_decimal = BigDecimal::from_str("999999999999999999.123").unwrap();
let value = Value::BigDecimal(huge_decimal);
let result = value.to::<i32>();
assert!(result.is_err());
}
#[test]
fn test_as_int32_non_numeric_type_conversion_failed() {
use chrono::NaiveDate;
let date = NaiveDate::from_ymd_opt(2025, 1, 1).unwrap();
let value = Value::Date(date);
let result = value.to::<i32>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionFailed { from, to }) => {
assert_eq!(from, DataType::Date);
assert_eq!(to, DataType::Int32);
}
_ => panic!("Expected ConversionFailed error"),
}
use chrono::NaiveTime;
let time = NaiveTime::from_hms_opt(12, 30, 45).unwrap();
let value = Value::Time(time);
assert!(value.to::<i32>().is_err());
use chrono::DateTime;
let datetime = DateTime::from_timestamp(1_000_000_000, 0)
.unwrap()
.naive_utc();
let value = Value::DateTime(datetime);
assert!(value.to::<i32>().is_err());
}
#[test]
fn test_as_int64_non_numeric_type_conversion_failed() {
use chrono::NaiveTime;
let time = NaiveTime::from_hms_opt(12, 30, 45).unwrap();
let value = Value::Time(time);
let result = value.to::<i64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionFailed { from, to }) => {
assert_eq!(from, DataType::Time);
assert_eq!(to, DataType::Int64);
}
_ => panic!("Expected ConversionFailed error"),
}
use chrono::NaiveDate;
let date = NaiveDate::from_ymd_opt(2025, 1, 1).unwrap();
let value = Value::Date(date);
assert!(value.to::<i64>().is_err());
}
#[test]
fn test_as_int64_big_types_edge_cases() {
use bigdecimal::BigDecimal;
use num_bigint::BigInt;
use std::str::FromStr;
let huge_bigint = BigInt::from_str("99999999999999999999").unwrap();
let value = Value::BigInteger(huge_bigint);
let result = value.to::<i64>();
assert!(result.is_err());
let decimal = BigDecimal::from_str("123.456").unwrap();
let value = Value::BigDecimal(decimal);
let result = value.to::<i64>();
assert!(result.is_ok());
assert_eq!(result.unwrap(), 123);
}
#[test]
fn test_as_float64_non_numeric_type_conversion_failed() {
use chrono::{
DateTime,
Utc,
};
let datetime = DateTime::from_timestamp(1_000_000_000, 0)
.unwrap()
.naive_utc();
let value = Value::DateTime(datetime);
let result = value.to::<f64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionFailed { from, to }) => {
assert_eq!(from, DataType::DateTime);
assert_eq!(to, DataType::Float64);
}
_ => panic!("Expected ConversionFailed error"),
}
let instant = Utc::now();
let value = Value::Instant(instant);
assert!(value.to::<f64>().is_err());
use chrono::NaiveDate;
let date = NaiveDate::from_ymd_opt(2025, 1, 1).unwrap();
let value = Value::Date(date);
assert!(value.to::<f64>().is_err());
use chrono::NaiveTime;
let time = NaiveTime::from_hms_opt(12, 30, 45).unwrap();
let value = Value::Time(time);
assert!(value.to::<f64>().is_err());
}
#[test]
fn test_float32_as_bool_conversion() {
let f32_zero = Value::Float32(0.0);
let f32_nonzero = Value::Float32(3.5);
assert!(f32_zero.to::<bool>().is_err());
assert!(f32_nonzero.to::<bool>().is_err());
match f32_zero.to::<bool>() {
Err(ValueError::ConversionFailed { from, to }) => {
assert_eq!(from, DataType::Float32);
assert_eq!(to, DataType::Bool);
}
_ => panic!("Expected ConversionFailed error"),
}
}
#[test]
fn test_char_numeric_conversions() {
let char_val = Value::Char('A');
assert_eq!(char_val.to::<i32>().unwrap(), 65);
assert_eq!(char_val.to::<i64>().unwrap(), 65);
assert_eq!(char_val.to::<f64>().unwrap(), 65.0);
}
#[test]
fn test_float_to_int64_conversions() {
let f32_val = Value::Float32(42.7);
assert_eq!(f32_val.to::<i64>().unwrap(), 42);
let f64_val = Value::Float64(123.9);
assert_eq!(f64_val.to::<i64>().unwrap(), 123);
}
#[test]
fn test_float_to_int_conversions_reject_non_finite_values() {
assert!(Value::Float64(f64::INFINITY).to::<i32>().is_err());
assert!(Value::Float64(f64::NEG_INFINITY).to::<i32>().is_err());
assert!(Value::Float64(f64::NAN).to::<i32>().is_err());
assert!(Value::Float32(f32::INFINITY).to::<i64>().is_err());
assert!(Value::Float32(f32::NEG_INFINITY).to::<i64>().is_err());
assert!(Value::Float32(f32::NAN).to::<i64>().is_err());
}
#[test]
fn test_float_to_int_conversions_reject_out_of_range_values() {
assert!(Value::Float64(i32::MAX as f64 + 1.0).to::<i32>().is_err());
assert!(Value::Float64(i32::MIN as f64 - 1.0).to::<i32>().is_err());
assert!(Value::Float64(i64::MAX as f64 * 2.0).to::<i64>().is_err());
assert!(Value::Float64(i64::MIN as f64 * 2.0).to::<i64>().is_err());
}
#[test]
fn test_uint128_to_int64_overflow() {
use std::str::FromStr;
let huge_val = u128::from_str("99999999999999999999").unwrap();
let value = Value::UInt128(huge_val);
let result = value.to::<i64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError"),
}
}
#[test]
fn test_as_int64_bool_conversion() {
let value_true = Value::Bool(true);
assert_eq!(value_true.to::<i64>().unwrap(), 1i64);
let value_false = Value::Bool(false);
assert_eq!(value_false.to::<i64>().unwrap(), 0i64);
}
#[test]
fn test_as_int64_int128_overflow() {
let value_max = Value::Int128(i128::MAX);
let result = value_max.to::<i64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for i128 overflow"),
}
let value_min = Value::Int128(i128::MIN);
let result = value_min.to::<i64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for i128 underflow"),
}
}
#[test]
fn test_as_int64_uint64_overflow() {
let value = Value::UInt64(u64::MAX);
let result = value.to::<i64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for u64 overflow"),
}
let value = Value::UInt64(i64::MAX as u64 + 1);
let result = value.to::<i64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for u64 just over i64::MAX"),
}
}
#[test]
fn test_as_int64_uint128_overflow() {
let value = Value::UInt128(u128::MAX);
let result = value.to::<i64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for u128 overflow"),
}
let large_value = Value::UInt128(i64::MAX as u128 + 1000);
let result = large_value.to::<i64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
assert!(msg.contains("range"));
}
_ => panic!("Expected ConversionError for large u128"),
}
}
#[test]
fn test_as_int64_bigdecimal_conversion_failed() {
use std::str::FromStr;
let huge_decimal = BigDecimal::from_str("999999999999999999999.123").unwrap();
let value = Value::BigDecimal(huge_decimal);
let result = value.to::<i64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
}
_ => panic!("Expected ConversionError for BigDecimal conversion"),
}
let tiny_decimal = BigDecimal::from_str("-999999999999999999999.123").unwrap();
let value = Value::BigDecimal(tiny_decimal);
let result = value.to::<i64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("i64"));
}
_ => panic!("Expected ConversionError for negative BigDecimal conversion"),
}
}
#[test]
fn test_as_float64_string_parse_failed() {
let value = Value::String("not_a_number".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("Cannot convert"));
assert!(msg.contains("not_a_number"));
assert!(msg.contains("f64"));
}
_ => panic!("Expected ConversionError for string parse failure"),
}
let value = Value::String("".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
let value = Value::String("12.34xyz".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
let value = Value::String("1.2.3".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
}
#[test]
fn test_as_float64_biginteger_conversion_edge_cases() {
use std::str::FromStr;
let normal_value = Value::BigInteger(BigInt::from(12345));
assert_eq!(normal_value.to::<f64>().unwrap(), 12345.0);
let huge_bigint = BigInt::from_str(&"9".repeat(400)).unwrap();
let value = Value::BigInteger(huge_bigint);
let result = value.to::<f64>();
assert!(result.is_err());
let neg_huge_bigint = BigInt::from_str(&format!("-{}", "9".repeat(400))).unwrap();
let value = Value::BigInteger(neg_huge_bigint);
let result = value.to::<f64>();
assert!(result.is_err());
let zero_bigint = BigInt::from(0);
let value = Value::BigInteger(zero_bigint);
assert_eq!(value.to::<f64>().unwrap(), 0.0);
}
#[test]
fn test_as_float64_bigdecimal_conversion_edge_cases() {
use std::str::FromStr;
let normal_value = Value::BigDecimal(BigDecimal::from_str("123.456").unwrap());
assert!((normal_value.to::<f64>().unwrap() - 123.456).abs() < 1e-10);
let huge_decimal = BigDecimal::from_str("1e400").unwrap();
let value = Value::BigDecimal(huge_decimal);
let result = value.to::<f64>();
assert!(result.is_err());
let neg_huge_decimal = BigDecimal::from_str("-1e400").unwrap();
let value = Value::BigDecimal(neg_huge_decimal);
let result = value.to::<f64>();
assert!(result.is_err());
let tiny_decimal = BigDecimal::from_str("1e-400").unwrap();
let value = Value::BigDecimal(tiny_decimal);
let result = value.to::<f64>();
assert!(result.is_ok());
let float_result = result.unwrap();
assert!(float_result >= 0.0);
let zero_decimal = BigDecimal::from_str("0.0").unwrap();
let value = Value::BigDecimal(zero_decimal);
assert_eq!(value.to::<f64>().unwrap(), 0.0);
}
#[test]
fn test_as_float64_bool_type_all_branches() {
let value_true = Value::Bool(true);
let result = value_true.to::<f64>();
assert!(result.is_ok());
assert_eq!(result.unwrap(), 1.0);
let value_false = Value::Bool(false);
let result = value_false.to::<f64>();
assert!(result.is_ok());
assert_eq!(result.unwrap(), 0.0);
assert_ne!(
value_true.to::<f64>().unwrap(),
value_false.to::<f64>().unwrap()
);
}
#[test]
fn test_as_float64_string_parse_all_error_cases() {
let value = Value::String("abc".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(msg)) => {
assert!(msg.contains("Cannot convert"));
assert!(msg.contains("abc"));
assert!(msg.contains("f64"));
}
_ => panic!("Expected ConversionError"),
}
let value = Value::String("".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
match result {
Err(ValueError::ConversionError(_)) => {
}
_ => panic!("Expected ConversionError for empty string"),
}
let value = Value::String("12.34abc".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
let value = Value::String("1.2.3".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
let value = Value::String("+".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
let value = Value::String("-".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
let value = Value::String(" 123.45 ".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
let value = Value::String("@#$%".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
let value = Value::String("一二三".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
let value = Value::String("123abc456".to_string());
let result = value.to::<f64>();
assert!(result.is_err());
let valid_value = Value::String("123.45".to_string());
assert!(valid_value.to::<f64>().is_ok());
assert_eq!(valid_value.to::<f64>().unwrap(), 123.45);
}
#[test]
fn test_to_unsigned_with_range_checks() {
assert_eq!(Value::UInt8(42).to::<u16>().unwrap(), 42u16);
assert_eq!(Value::UInt16(42).to::<u32>().unwrap(), 42u32);
assert_eq!(Value::UInt32(42).to::<u64>().unwrap(), 42u64);
assert_eq!(Value::UInt64(42).to::<u128>().unwrap(), 42u128);
assert_eq!(Value::Int8(42).to::<u16>().unwrap(), 42u16);
assert_eq!(Value::Int16(42).to::<u32>().unwrap(), 42u32);
assert_eq!(Value::Int32(42).to::<u64>().unwrap(), 42u64);
assert_eq!(Value::Int64(42).to::<u128>().unwrap(), 42u128);
assert_eq!(Value::Bool(true).to::<u8>().unwrap(), 1u8);
assert_eq!(Value::Char('A').to::<u16>().unwrap(), 65u16);
assert_eq!(Value::String("255".to_string()).to::<u8>().unwrap(), 255u8);
}
#[test]
fn test_to_unsigned_range_failures() {
assert!(Value::Int8(-1).to::<u16>().is_err());
assert!(Value::Int16(-1).to::<u32>().is_err());
assert!(Value::UInt16(256).to::<u8>().is_err());
assert!(Value::UInt32(u16::MAX as u32 + 1).to::<u16>().is_err());
assert!(Value::UInt64(u32::MAX as u64 + 1).to::<u32>().is_err());
assert!(Value::UInt128(u64::MAX as u128 + 1).to::<u64>().is_err());
}
#[test]
fn test_to_f32_extended_sources() {
assert_eq!(Value::Bool(true).to::<f32>().unwrap(), 1.0f32);
assert_eq!(Value::Char('A').to::<f32>().unwrap(), 65.0f32);
assert_eq!(Value::Int32(42).to::<f32>().unwrap(), 42.0f32);
assert_eq!(Value::UInt64(42).to::<f32>().unwrap(), 42.0f32);
assert_eq!(Value::Float64(3.5).to::<f32>().unwrap(), 3.5f32);
assert_eq!(
Value::String("2.5".to_string()).to::<f32>().unwrap(),
2.5f32
);
}
#[test]
fn test_to_f32_range_failures() {
assert!(Value::Float64(f64::MAX).to::<f32>().is_err());
}
#[test]
fn test_big_number_to_f32_and_f64_failures() {
let huge_big_int = BigInt::from_str(&"9".repeat(2000)).unwrap();
assert!(Value::BigInteger(huge_big_int.clone()).to::<f32>().is_err());
assert!(Value::BigInteger(huge_big_int).to::<f64>().is_err());
let huge_big_decimal = BigDecimal::from_str("1.0e10000").unwrap();
assert!(
Value::BigDecimal(huge_big_decimal.clone())
.to::<f32>()
.is_err()
);
assert!(Value::BigDecimal(huge_big_decimal).to::<f64>().is_err());
}
#[test]
fn test_narrow_signed_integer_converters_accept_numeric_sources() {
let cases = vec![
(Value::Bool(true), 1i128),
(Value::Bool(false), 0),
(Value::Char('A'), 65),
(Value::Int8(-8), -8),
(Value::Int16(-16), -16),
(Value::Int32(-32), -32),
(Value::Int64(-64), -64),
(Value::Int128(-128), -128),
(Value::IntSize(-256), -256),
(Value::UInt8(8), 8),
(Value::UInt16(16), 16),
(Value::UInt32(32), 32),
(Value::UInt64(64), 64),
(Value::UInt128(128), 128),
(Value::UIntSize(512), 512),
(Value::Float32(12.9), 12),
(Value::Float64(-34.7), -34),
(Value::String("-55".to_string()), -55),
(Value::BigInteger(BigInt::from(99)), 99),
(Value::BigDecimal(BigDecimal::from(123)), 123),
];
for (value, expected) in cases {
assert_eq!(value.to::<i128>().unwrap(), expected);
}
assert_eq!(Value::UInt16(127).to::<i8>().unwrap(), 127);
assert_eq!(Value::Float64(-12.9).to::<i8>().unwrap(), -12);
assert_eq!(
Value::BigDecimal(BigDecimal::from(32_000))
.to::<i16>()
.unwrap(),
32_000
);
assert_eq!(
Value::String("-123".to_string()).to::<isize>().unwrap(),
-123
);
}
#[test]
fn test_narrow_signed_integer_converters_reject_invalid_values() {
assert!(Value::String("128".to_string()).to::<i8>().is_err());
assert!(Value::Char('\u{80}').to::<i8>().is_err());
assert!(Value::Int32(i16::MAX as i32 + 1).to::<i16>().is_err());
assert!(Value::Int128(isize::MAX as i128 + 1).to::<isize>().is_err());
assert!(Value::UInt128(i128::MAX as u128 + 1).to::<i128>().is_err());
assert!(Value::Float64(f64::INFINITY).to::<i128>().is_err());
assert!(Value::Float64(f64::MAX).to::<i128>().is_err());
assert!(Value::String("invalid".to_string()).to::<i16>().is_err());
let too_big = BigInt::from(i128::MAX) + BigInt::from(1u8);
assert!(Value::BigInteger(too_big).to::<i128>().is_err());
assert!(
Value::BigDecimal(BigDecimal::from_str("1e100").unwrap())
.to::<i128>()
.is_err()
);
let date = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
assert!(matches!(
Value::Date(date).to::<i128>(),
Err(ValueError::ConversionFailed { .. })
));
assert!(matches!(
Value::Empty(DataType::Int128).to::<i128>(),
Err(ValueError::NoValue)
));
}
#[test]
fn test_usize_converter_accepts_integer_sources() {
let cases = vec![
(Value::Bool(true), 1usize),
(Value::Bool(false), 0),
(Value::Char('A'), 65),
(Value::Int8(8), 8),
(Value::Int16(16), 16),
(Value::Int32(32), 32),
(Value::Int64(64), 64),
(Value::Int128(128), 128),
(Value::IntSize(256), 256),
(Value::UInt8(8), 8),
(Value::UInt16(16), 16),
(Value::UInt32(32), 32),
(Value::UInt64(64), 64),
(Value::UInt128(128), 128),
(Value::UIntSize(512), 512),
(Value::String("1024".to_string()), 1024),
];
for (value, expected) in cases {
assert_eq!(value.to::<usize>().unwrap(), expected);
}
}
#[test]
fn test_usize_converter_rejects_invalid_values() {
assert!(Value::Int8(-1).to::<usize>().is_err());
assert!(Value::IntSize(-1).to::<usize>().is_err());
assert!(
Value::UInt128(usize::MAX as u128 + 1)
.to::<usize>()
.is_err()
);
assert!(Value::String("invalid".to_string()).to::<usize>().is_err());
assert!(matches!(
Value::Empty(DataType::UIntSize).to::<usize>(),
Err(ValueError::NoValue)
));
assert!(matches!(
Value::Float64(1.0).to::<usize>(),
Err(ValueError::ConversionFailed { .. })
));
}