Skip to content

Commit 31d4e5d

Browse files
committed
Better CAST errors
Resolves: #184
1 parent 9c2f706 commit 31d4e5d

File tree

3 files changed

+35
-17
lines changed

3 files changed

+35
-17
lines changed

Diff for: src/data/value/cast.rs

+26-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
super::{Convert, Value, ValueError},
2+
super::{Convert, Value, ValueError, ValueType},
33
crate::{Error, Result},
44
chrono::{NaiveDate, NaiveDateTime, NaiveTime, ParseError},
55
std::convert::TryInto,
@@ -13,6 +13,13 @@ pub trait CastWithRules<Output> {
1313
fn cast_with_rule(self, rule: Self) -> Result<Output>;
1414
}
1515

16+
fn failed_cast(value: &Value, value_type: ValueType) -> Error {
17+
Error::Value(ValueError::FailedCast(value.clone(), value_type))
18+
}
19+
fn unimplemented_cast(value: &Value, value_type: ValueType) -> Error {
20+
Error::Value(ValueError::FailedCast(value.clone().into(), value_type))
21+
}
22+
1623
// Cores
1724
impl Cast<bool> for Value {
1825
fn cast(self) -> Result<bool> {
@@ -21,24 +28,24 @@ impl Cast<bool> for Value {
2128
Value::I64(value) => match value {
2229
1 => true,
2330
0 => false,
24-
_ => return Err(ValueError::ImpossibleCast.into()),
31+
_ => return Err(failed_cast(&self, ValueType::Bool)),
2532
},
2633
Value::F64(value) => {
2734
if value.eq(&1.0) {
2835
true
2936
} else if value.eq(&0.0) {
3037
false
3138
} else {
32-
return Err(ValueError::ImpossibleCast.into());
39+
return Err(failed_cast(&self, ValueType::Bool));
3340
}
3441
}
3542
Value::Str(value) => match value.to_uppercase().as_str() {
3643
"TRUE" => true,
3744
"FALSE" => false,
3845
_ => return Err(ValueError::ImpossibleCast.into()),
3946
},
40-
Value::Null => return Err(ValueError::ImpossibleCast.into()),
41-
_ => return Err(Error::Value(ValueError::UnimplementedCast)),
47+
Value::Null => return Err(failed_cast(&self, ValueType::Bool)),
48+
_ => return Err(unimplemented_cast(&self, ValueType::Bool)),
4249
})
4350
}
4451
}
@@ -54,13 +61,15 @@ impl Cast<u64> for Value {
5461
}
5562
}
5663
Value::U64(value) => value,
57-
Value::I64(value) => value.try_into().map_err(|_| ValueError::ImpossibleCast)?,
64+
Value::I64(value) => value
65+
.try_into()
66+
.map_err(|_| failed_cast(&self, ValueType::U64))?,
5867
Value::F64(value) => (value.trunc() as i64)
5968
.try_into()
60-
.map_err(|_| ValueError::ImpossibleCast)?,
69+
.map_err(|_| failed_cast(&self, ValueType::U64))?,
6170
Value::Str(value) => lexical::parse(value).map_err(|_| ValueError::ImpossibleCast)?,
62-
Value::Null => return Err(ValueError::ImpossibleCast.into()),
63-
_ => return Err(Error::Value(ValueError::UnimplementedCast)),
71+
Value::Null => return Err(failed_cast(&self, ValueType::U64)),
72+
_ => return Err(unimplemented_cast(&self, ValueType::U64)),
6473
})
6574
}
6675
}
@@ -75,12 +84,14 @@ impl Cast<i64> for Value {
7584
0
7685
}
7786
}
78-
Value::U64(value) => value.try_into().map_err(|_| ValueError::ImpossibleCast)?,
87+
Value::U64(value) => value
88+
.try_into()
89+
.map_err(|_| failed_cast(&self, ValueType::I64))?,
7990
Value::I64(value) => value,
8091
Value::F64(value) => value.trunc() as i64,
8192
Value::Str(value) => lexical::parse(value).map_err(|_| ValueError::ImpossibleCast)?,
82-
Value::Null => return Err(ValueError::ImpossibleCast.into()),
83-
_ => return Err(Error::Value(ValueError::UnimplementedCast)),
93+
Value::Null => return Err(failed_cast(&self, ValueType::I64)),
94+
_ => return Err(unimplemented_cast(&self, ValueType::I64)),
8495
})
8596
}
8697
}
@@ -101,8 +112,8 @@ impl Cast<f64> for Value {
101112
Value::Str(value) => {
102113
fast_float::parse(value).map_err(|_| ValueError::ImpossibleCast)?
103114
}
104-
Value::Null => return Err(ValueError::ImpossibleCast.into()),
105-
_ => return Err(Error::Value(ValueError::UnimplementedCast)),
115+
Value::Null => return Err(failed_cast(&self, ValueType::F64)),
116+
_ => return Err(unimplemented_cast(&self, ValueType::F64)),
106117
})
107118
}
108119
}
@@ -116,7 +127,7 @@ impl Cast<String> for Value {
116127
Value::Str(value) => value,
117128
Value::Timestamp(value) => lexical::to_string(value),
118129
Value::Null => String::from("NULL"),
119-
_ => return Err(Error::Value(ValueError::UnimplementedCast)),
130+
_ => return Err(unimplemented_cast(&self, ValueType::Str)),
120131
})
121132
}
122133
}

Diff for: src/data/value/error.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
use {super::Value, serde::Serialize, std::fmt::Debug, thiserror::Error};
1+
use {
2+
crate::{Value, ValueType},
3+
serde::Serialize,
4+
std::fmt::Debug,
5+
thiserror::Error,
6+
};
27

38
#[derive(Error, Serialize, Debug, PartialEq)]
49
pub enum ValueError {
@@ -30,6 +35,8 @@ pub enum ValueError {
3035

3136
#[error("impossible cast")]
3237
ImpossibleCast, // Bad error-- phase out
38+
#[error("failed to cast {0:?} into {1:?}")]
39+
FailedCast(Value, ValueType),
3340

3441
#[error("date time failed to parse: {0}")]
3542
DateTimeParseError(String),

Diff for: src/data/value/value_type/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use {
77
std::fmt::Debug,
88
};
99

10-
#[derive(Clone, Serialize, Deserialize, Debug)]
10+
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
1111
pub enum ValueType {
1212
Bool,
1313
U64,

0 commit comments

Comments
 (0)