use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Value {
Null,
Bool(bool),
Int(i64),
Float(f64),
Text(String),
Bytes(Vec<u8>),
Array(Vec<Value>),
Map(HashMap<String, Value>),
Uuid(uuid::Uuid),
DateTime(chrono::DateTime<chrono::Utc>),
Json(serde_json::Value),
}
impl Value {
pub fn is_null(&self) -> bool {
matches!(self, Value::Null)
}
pub fn as_str(&self) -> Option<&str> {
match self {
Value::Text(s) => Some(s.as_str()),
_ => None,
}
}
pub fn as_i64(&self) -> Option<i64> {
match self {
Value::Int(i) => Some(*i),
_ => None,
}
}
pub fn as_f64(&self) -> Option<f64> {
match self {
Value::Float(f) => Some(*f),
Value::Int(i) => Some(*i as f64),
_ => None,
}
}
pub fn as_bool(&self) -> Option<bool> {
match self {
Value::Bool(b) => Some(*b),
_ => None,
}
}
}
impl From<bool> for Value {
fn from(v: bool) -> Self { Value::Bool(v) }
}
impl From<i32> for Value {
fn from(v: i32) -> Self { Value::Int(v as i64) }
}
impl From<i64> for Value {
fn from(v: i64) -> Self { Value::Int(v) }
}
impl From<f32> for Value {
fn from(v: f32) -> Self { Value::Float(v as f64) }
}
impl From<f64> for Value {
fn from(v: f64) -> Self { Value::Float(v) }
}
impl From<String> for Value {
fn from(v: String) -> Self { Value::Text(v) }
}
impl From<&str> for Value {
fn from(v: &str) -> Self { Value::Text(v.to_owned()) }
}
impl From<uuid::Uuid> for Value {
fn from(v: uuid::Uuid) -> Self { Value::Uuid(v) }
}
impl From<chrono::DateTime<chrono::Utc>> for Value {
fn from(v: chrono::DateTime<chrono::Utc>) -> Self { Value::DateTime(v) }
}
impl From<serde_json::Value> for Value {
fn from(v: serde_json::Value) -> Self { Value::Json(v) }
}
impl<T: Into<Value>> From<Option<T>> for Value {
fn from(v: Option<T>) -> Self {
match v {
Some(inner) => inner.into(),
None => Value::Null,
}
}
}
pub type Row = HashMap<String, Value>;