use std::net::{Ipv4Addr, Ipv6Addr};
use uuid::Uuid;
use crate::types::TypeDesc;
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
Nothing,
UInt8(u8),
Bool(bool),
UInt16(u16),
UInt32(u32),
UInt64(u64),
UInt128(u128),
UInt256([u8; 32]),
Int8(i8),
Int16(i16),
Int32(i32),
Int64(i64),
Int128(i128),
Int256([u8; 32]),
Float32(f32),
Float64(f64),
Float16(f32),
BFloat16(f32),
String(Vec<u8>),
FixedString(Vec<u8>),
Date(u16),
Date32(i32),
DateTime(u32),
DateTime64(i64),
Uuid(Uuid),
Ipv4(Ipv4Addr),
Ipv6(Ipv6Addr),
Decimal32(i32),
Decimal64(i64),
Decimal128(i128),
Decimal256([u8; 32]),
Enum8(i8),
Enum16(i16),
Nullable(Option<Box<Value>>),
Array(Vec<Value>),
Map(Vec<(Value, Value)>),
Tuple(Vec<Value>),
Variant {
index: u8,
value: Box<Value>,
},
VariantNull,
JsonObject(Vec<(String, Value)>),
Dynamic {
ty: Box<TypeDesc>,
value: Box<Value>,
},
DynamicNull,
}
impl Value {
#[must_use]
pub fn type_name(&self) -> &'static str {
match self {
Value::Nothing => "Nothing",
Value::UInt8(_) => "UInt8",
Value::Bool(_) => "Bool",
Value::UInt16(_) => "UInt16",
Value::UInt32(_) => "UInt32",
Value::UInt64(_) => "UInt64",
Value::UInt128(_) => "UInt128",
Value::UInt256(_) => "UInt256",
Value::Int8(_) => "Int8",
Value::Int16(_) => "Int16",
Value::Int32(_) => "Int32",
Value::Int64(_) => "Int64",
Value::Int128(_) => "Int128",
Value::Int256(_) => "Int256",
Value::Float32(_) => "Float32",
Value::Float64(_) => "Float64",
Value::Float16(_) => "Float16",
Value::BFloat16(_) => "BFloat16",
Value::String(_) => "String",
Value::FixedString(_) => "FixedString",
Value::Date(_) => "Date",
Value::Date32(_) => "Date32",
Value::DateTime(_) => "DateTime",
Value::DateTime64(_) => "DateTime64",
Value::Uuid(_) => "UUID",
Value::Ipv4(_) => "IPv4",
Value::Ipv6(_) => "IPv6",
Value::Decimal32(_) => "Decimal32",
Value::Decimal64(_) => "Decimal64",
Value::Decimal128(_) => "Decimal128",
Value::Decimal256(_) => "Decimal256",
Value::Enum8(_) => "Enum8",
Value::Enum16(_) => "Enum16",
Value::Nullable(_) => "Nullable",
Value::Array(_) => "Array",
Value::Map(_) => "Map",
Value::Tuple(_) => "Tuple",
Value::Variant { .. } | Value::VariantNull => "Variant",
Value::JsonObject(_) => "JSON",
Value::Dynamic { .. } | Value::DynamicNull => "Dynamic",
}
}
}
impl From<u8> for Value {
fn from(value: u8) -> Self {
Value::UInt8(value)
}
}
impl From<u16> for Value {
fn from(value: u16) -> Self {
Value::UInt16(value)
}
}
impl From<u32> for Value {
fn from(value: u32) -> Self {
Value::UInt32(value)
}
}
impl From<u64> for Value {
fn from(value: u64) -> Self {
Value::UInt64(value)
}
}
impl From<i8> for Value {
fn from(value: i8) -> Self {
Value::Int8(value)
}
}
impl From<i16> for Value {
fn from(value: i16) -> Self {
Value::Int16(value)
}
}
impl From<i32> for Value {
fn from(value: i32) -> Self {
Value::Int32(value)
}
}
impl From<i64> for Value {
fn from(value: i64) -> Self {
Value::Int64(value)
}
}
impl From<f32> for Value {
fn from(value: f32) -> Self {
Value::Float32(value)
}
}
impl From<f64> for Value {
fn from(value: f64) -> Self {
Value::Float64(value)
}
}
impl From<String> for Value {
fn from(value: String) -> Self {
Value::String(value.into_bytes())
}
}
impl From<&str> for Value {
fn from(value: &str) -> Self {
Value::String(value.as_bytes().to_vec())
}
}
impl From<Vec<u8>> for Value {
fn from(value: Vec<u8>) -> Self {
Value::String(value)
}
}
#[cfg(test)]
mod tests {
use super::Value;
use std::mem::size_of;
#[test]
fn value_size_is_stable() {
assert_eq!(size_of::<Value>(), 48);
}
}