use std::fmt;
use std::fmt::Display;
use std::fmt::Formatter;
use std::str::FromStr;
use serde::Deserialize;
use serde::Serialize;
use super::DataTypeCategory;
use super::data_type_parse_error::DataTypeParseError;
#[must_use]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum DataType {
Bool,
Char,
Int8,
Int16,
Int32,
Int64,
Int128,
UInt8,
UInt16,
UInt32,
UInt64,
UInt128,
Float32,
Float64,
String,
Date,
Time,
DateTime,
Instant,
BigInteger,
BigDecimal,
Duration,
Url,
StringMap,
Json,
}
impl DataType {
pub const ALL: &'static [DataType] = &[
DataType::Bool,
DataType::Char,
DataType::Int8,
DataType::Int16,
DataType::Int32,
DataType::Int64,
DataType::Int128,
DataType::UInt8,
DataType::UInt16,
DataType::UInt32,
DataType::UInt64,
DataType::UInt128,
DataType::Float32,
DataType::Float64,
DataType::String,
DataType::Date,
DataType::Time,
DataType::DateTime,
DataType::Instant,
DataType::BigInteger,
DataType::BigDecimal,
DataType::Duration,
DataType::Url,
DataType::StringMap,
DataType::Json,
];
#[must_use = "the data type category is returned"]
#[inline]
pub const fn category(self) -> DataTypeCategory {
match self {
DataType::Bool => DataTypeCategory::Boolean,
DataType::Char => DataTypeCategory::Character,
DataType::Int8 | DataType::Int16 | DataType::Int32 | DataType::Int64 | DataType::Int128 => {
DataTypeCategory::SignedInteger
}
DataType::UInt8 | DataType::UInt16 | DataType::UInt32 | DataType::UInt64 | DataType::UInt128 => {
DataTypeCategory::UnsignedInteger
}
DataType::Float32 | DataType::Float64 => DataTypeCategory::FloatingPoint,
DataType::String => DataTypeCategory::Text,
DataType::Date | DataType::Time | DataType::DateTime | DataType::Instant => DataTypeCategory::Temporal,
DataType::BigInteger | DataType::BigDecimal => DataTypeCategory::BigNumber,
DataType::Duration => DataTypeCategory::Duration,
DataType::Url => DataTypeCategory::Locator,
DataType::StringMap | DataType::Json => DataTypeCategory::Structured,
}
}
#[must_use]
#[inline]
pub const fn as_str(self) -> &'static str {
match self {
DataType::Bool => "bool",
DataType::Char => "char",
DataType::Int8 => "int8",
DataType::Int16 => "int16",
DataType::Int32 => "int32",
DataType::Int64 => "int64",
DataType::Int128 => "int128",
DataType::UInt8 => "uint8",
DataType::UInt16 => "uint16",
DataType::UInt32 => "uint32",
DataType::UInt64 => "uint64",
DataType::UInt128 => "uint128",
DataType::Float32 => "float32",
DataType::Float64 => "float64",
DataType::String => "string",
DataType::Date => "date",
DataType::Time => "time",
DataType::DateTime => "datetime",
DataType::Instant => "instant",
DataType::BigInteger => "biginteger",
DataType::BigDecimal => "bigdecimal",
DataType::Duration => "duration",
DataType::Url => "url",
DataType::StringMap => "stringmap",
DataType::Json => "json",
}
}
#[must_use]
#[inline]
pub const fn is_numeric(self) -> bool {
self.is_integer() || self.is_float() || self.is_big_number()
}
#[must_use]
#[inline]
pub const fn is_integer(self) -> bool {
self.is_signed_integer() || self.is_unsigned_integer()
}
#[must_use]
#[inline]
pub const fn is_signed_integer(self) -> bool {
matches!(
self,
DataType::Int8 | DataType::Int16 | DataType::Int32 | DataType::Int64 | DataType::Int128
)
}
#[must_use]
#[inline]
pub const fn is_unsigned_integer(self) -> bool {
matches!(
self,
DataType::UInt8 | DataType::UInt16 | DataType::UInt32 | DataType::UInt64 | DataType::UInt128
)
}
#[must_use]
#[inline]
pub const fn is_float(self) -> bool {
matches!(self, DataType::Float32 | DataType::Float64)
}
#[must_use]
#[inline]
pub const fn is_big_number(self) -> bool {
matches!(self, DataType::BigInteger | DataType::BigDecimal)
}
}
impl Display for DataType {
#[inline]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
formatter.write_str(self.as_str())
}
}
impl FromStr for DataType {
type Err = DataTypeParseError;
fn from_str(input: &str) -> Result<Self, Self::Err> {
Self::ALL
.iter()
.copied()
.find(|data_type| input.eq_ignore_ascii_case(data_type.as_str()))
.ok_or_else(|| DataTypeParseError::new(input))
}
}
impl From<DataType> for &'static str {
#[inline]
fn from(value: DataType) -> Self {
value.as_str()
}
}
impl From<&DataType> for &'static str {
#[inline]
fn from(value: &DataType) -> Self {
value.as_str()
}
}