use super::{Type, Value};
use crate::types::{FromSqlError, FromSqlResult};
use rust_decimal::prelude::*;
#[derive(Copy, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum TimeUnit {
Second,
Millisecond,
Microsecond,
Nanosecond,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
Null,
Boolean(bool),
TinyInt(i8),
SmallInt(i16),
Int(i32),
BigInt(i64),
HugeInt(i128),
UTinyInt(u8),
USmallInt(u16),
UInt(u32),
UBigInt(u64),
Float(f32),
Double(f64),
Decimal(Decimal),
Timestamp(TimeUnit, i64),
Text(&'a [u8]),
Blob(&'a [u8]),
Date32(i32),
Time64(TimeUnit, i64),
}
impl ValueRef<'_> {
#[inline]
pub fn data_type(&self) -> Type {
match *self {
ValueRef::Null => Type::Null,
ValueRef::Boolean(_) => Type::Boolean,
ValueRef::TinyInt(_) => Type::TinyInt,
ValueRef::SmallInt(_) => Type::SmallInt,
ValueRef::Int(_) => Type::Int,
ValueRef::BigInt(_) => Type::BigInt,
ValueRef::HugeInt(_) => Type::HugeInt,
ValueRef::UTinyInt(_) => Type::UTinyInt,
ValueRef::USmallInt(_) => Type::USmallInt,
ValueRef::UInt(_) => Type::UInt,
ValueRef::UBigInt(_) => Type::UBigInt,
ValueRef::Float(_) => Type::Float,
ValueRef::Double(_) => Type::Double,
ValueRef::Decimal(_) => Type::Decimal,
ValueRef::Timestamp(..) => Type::Timestamp,
ValueRef::Text(_) => Type::Text,
ValueRef::Blob(_) => Type::Blob,
ValueRef::Date32(_) => Type::Date32,
ValueRef::Time64(..) => Type::Time64,
}
}
}
impl<'a> ValueRef<'a> {
#[inline]
pub fn as_str(&self) -> FromSqlResult<&'a str> {
match *self {
ValueRef::Text(t) => std::str::from_utf8(t).map_err(|e| FromSqlError::Other(Box::new(e))),
_ => Err(FromSqlError::InvalidType),
}
}
#[inline]
pub fn as_blob(&self) -> FromSqlResult<&'a [u8]> {
match *self {
ValueRef::Blob(b) => Ok(b),
ValueRef::Text(t) => Ok(t),
_ => Err(FromSqlError::InvalidType),
}
}
}
impl From<ValueRef<'_>> for Value {
#[inline]
fn from(borrowed: ValueRef<'_>) -> Value {
match borrowed {
ValueRef::Null => Value::Null,
ValueRef::Boolean(i) => Value::Boolean(i),
ValueRef::TinyInt(i) => Value::TinyInt(i),
ValueRef::SmallInt(i) => Value::SmallInt(i),
ValueRef::Int(i) => Value::Int(i),
ValueRef::BigInt(i) => Value::BigInt(i),
ValueRef::HugeInt(i) => Value::HugeInt(i),
ValueRef::UTinyInt(i) => Value::UTinyInt(i),
ValueRef::USmallInt(i) => Value::USmallInt(i),
ValueRef::UInt(i) => Value::UInt(i),
ValueRef::UBigInt(i) => Value::UBigInt(i),
ValueRef::Float(i) => Value::Float(i),
ValueRef::Double(i) => Value::Double(i),
ValueRef::Decimal(i) => Value::Decimal(i),
ValueRef::Timestamp(tu, t) => Value::Timestamp(tu, t),
ValueRef::Text(s) => {
let s = std::str::from_utf8(s).expect("invalid UTF-8");
Value::Text(s.to_string())
}
ValueRef::Blob(b) => Value::Blob(b.to_vec()),
ValueRef::Date32(d) => Value::Date32(d),
ValueRef::Time64(t, d) => Value::Time64(t, d),
}
}
}
impl<'a> From<&'a str> for ValueRef<'a> {
#[inline]
fn from(s: &str) -> ValueRef<'_> {
ValueRef::Text(s.as_bytes())
}
}
impl<'a> From<&'a [u8]> for ValueRef<'a> {
#[inline]
fn from(s: &[u8]) -> ValueRef<'_> {
ValueRef::Blob(s)
}
}
impl<'a> From<&'a Value> for ValueRef<'a> {
#[inline]
fn from(value: &'a Value) -> ValueRef<'a> {
match *value {
Value::Null => ValueRef::Null,
Value::Boolean(i) => ValueRef::Boolean(i),
Value::TinyInt(i) => ValueRef::TinyInt(i),
Value::SmallInt(i) => ValueRef::SmallInt(i),
Value::Int(i) => ValueRef::Int(i),
Value::BigInt(i) => ValueRef::BigInt(i),
Value::HugeInt(i) => ValueRef::HugeInt(i),
Value::UTinyInt(i) => ValueRef::UTinyInt(i),
Value::USmallInt(i) => ValueRef::USmallInt(i),
Value::UInt(i) => ValueRef::UInt(i),
Value::UBigInt(i) => ValueRef::UBigInt(i),
Value::Float(i) => ValueRef::Float(i),
Value::Double(i) => ValueRef::Double(i),
Value::Decimal(i) => ValueRef::Decimal(i),
Value::Timestamp(tu, t) => ValueRef::Timestamp(tu, t),
Value::Text(ref s) => ValueRef::Text(s.as_bytes()),
Value::Blob(ref b) => ValueRef::Blob(b),
Value::Date32(d) => ValueRef::Date32(d),
Value::Time64(t, d) => ValueRef::Time64(t, d),
}
}
}
impl<'a, T> From<Option<T>> for ValueRef<'a>
where
T: Into<ValueRef<'a>>,
{
#[inline]
fn from(s: Option<T>) -> ValueRef<'a> {
match s {
Some(x) => x.into(),
None => ValueRef::Null,
}
}
}