use super::error::{Error, ValueError};
use chrono;
use chrono_tz;
use rust_decimal;
use std::result::Result;
#[derive(PartialEq, Debug, Clone)]
pub enum CellValue {
Null,
Text(String),
Varying(String),
Short(i16),
Long(i32),
Float(f32),
Time(chrono::NaiveTime),
Date(chrono::NaiveDate),
Double(f64),
TimeStamp(chrono::NaiveDateTime),
BlobBinary(Vec<u8>),
BlobText(Vec<u8>),
Int64(i64),
Int128(i128),
TimeStampTz(chrono::DateTime<chrono_tz::Tz>),
TimeTz((chrono::NaiveTime, chrono_tz::Tz)),
Decimal(rust_decimal::Decimal),
Boolean(bool),
}
pub trait CellValueToVal<T> {
fn to_val(self) -> Result<T, Error>
where
Self: std::marker::Sized;
}
impl<T> CellValueToVal<Option<T>> for CellValue
where
CellValue: CellValueToVal<T>,
{
fn to_val(self) -> Result<Option<T>, Error> {
match self {
CellValue::Null => Ok(None),
_ => Ok(Some(self.to_val()?)),
}
}
}
impl CellValueToVal<String> for CellValue {
fn to_val(self) -> Result<String, Error> {
match self {
CellValue::Text(v) => Ok(v.to_string()),
CellValue::Varying(v) => Ok(v.to_string()),
CellValue::BlobBinary(v) => Ok(String::from_utf8_lossy(&v).to_string()),
CellValue::BlobText(v) => Ok(String::from_utf8_lossy(&v).to_string()),
_ => Err(Error::ValueError(ValueError::new("Can't convert string"))),
}
}
}
impl CellValueToVal<i64> for CellValue {
fn to_val(self) -> Result<i64, Error> {
match self {
CellValue::Short(v) => Ok(v.into()),
CellValue::Long(v) => Ok(v.into()),
CellValue::Int64(v) => Ok(v.into()),
_ => Err(Error::ValueError(ValueError::new("Can't convert int"))),
}
}
}
impl CellValueToVal<i32> for CellValue {
fn to_val(self) -> Result<i32, Error> {
CellValueToVal::<i64>::to_val(self).map(|i| i as i32)
}
}
impl CellValueToVal<i16> for CellValue {
fn to_val(self) -> Result<i16, Error> {
CellValueToVal::<i64>::to_val(self).map(|i| i as i16)
}
}
impl CellValueToVal<f64> for CellValue {
fn to_val(self) -> Result<f64, Error> {
match self {
CellValue::Double(v) => Ok(v),
_ => Err(Error::ValueError(ValueError::new("Can't convert double"))),
}
}
}
impl CellValueToVal<f32> for CellValue {
fn to_val(self) -> Result<f32, Error> {
match self {
CellValue::Float(v) => Ok(v),
_ => Err(Error::ValueError(ValueError::new("Can't convert float"))),
}
}
}
impl CellValueToVal<Vec<u8>> for CellValue {
fn to_val(self) -> Result<Vec<u8>, Error> {
match self {
CellValue::BlobBinary(v) => Ok(v.clone()),
CellValue::BlobText(v) => Ok(v.clone()),
_ => Err(Error::ValueError(ValueError::new("Can't convert binary"))),
}
}
}
impl CellValueToVal<bool> for CellValue {
fn to_val(self) -> Result<bool, Error> {
match self {
CellValue::Boolean(v) => Ok(v),
_ => Err(Error::ValueError(ValueError::new("Can't convert bool"))),
}
}
}
impl CellValueToVal<chrono::NaiveTime> for CellValue {
fn to_val(self) -> Result<chrono::NaiveTime, Error> {
match self {
CellValue::Time(v) => Ok(v),
_ => Err(Error::ValueError(ValueError::new("Can't convert time"))),
}
}
}
impl CellValueToVal<chrono::NaiveDate> for CellValue {
fn to_val(self) -> Result<chrono::NaiveDate, Error> {
match self {
CellValue::Date(v) => Ok(v),
_ => Err(Error::ValueError(ValueError::new("Can't convert date"))),
}
}
}
impl CellValueToVal<chrono::NaiveDateTime> for CellValue {
fn to_val(self) -> Result<chrono::NaiveDateTime, Error> {
match self {
CellValue::TimeStamp(v) => Ok(v),
_ => Err(Error::ValueError(ValueError::new(
"Can't convert timestamp",
))),
}
}
}
impl CellValueToVal<rust_decimal::Decimal> for CellValue {
fn to_val(self) -> Result<rust_decimal::Decimal, Error> {
match self {
CellValue::Decimal(v) => Ok(v),
_ => Err(Error::ValueError(ValueError::new("Can't convert decimal"))),
}
}
}
impl CellValueToVal<(chrono::NaiveTime, chrono_tz::Tz)> for CellValue {
fn to_val(self) -> Result<(chrono::NaiveTime, chrono_tz::Tz), Error> {
match self {
CellValue::TimeTz(v) => Ok(v),
_ => Err(Error::ValueError(ValueError::new(
"Can't convert time with time zone",
))),
}
}
}
impl CellValueToVal<chrono::DateTime<chrono_tz::Tz>> for CellValue {
fn to_val(self) -> Result<chrono::DateTime<chrono_tz::Tz>, Error> {
match self {
CellValue::TimeStampTz(v) => Ok(v),
_ => Err(Error::ValueError(ValueError::new(
"Can't convert timestamp with time zone",
))),
}
}
}